반응형
안녕하세요. 훈츠 입니다. 이번 시간에는 포인터에 대해 정리 해보려고 합니다. 어렵게 느껴졌는데 차근차근 정리 해보니 정리가 되네요. 같이 한번 보시죠.
포인터
- 메모리 에서 데이터를 읽어오는 방법
- 메모리 주소 -> 데이터 위치
- 메모리의 주소와 데이터 타입을 알면, 데이터를 읽거나 저장 할 수있다.
- 포인터의 역활 : 임의의 메모리에 접근하여 값을 저장하거나 읽는 역활
- 포인터 변수 : 메모리 주소를 저장 하는 변수
- 일반 변수와 포인터 변수의 공통점과 차이점
공통점 | 차이점 | |
일반 변수 | 값 저장 | 상수 저장 |
포인터 변수 | 값 저장 | 메모리 주소 저장 |
'*' 참조 연산자 아스트리크
- 선언된 변수가 포인터 변수임을 나태내는 역활
- ex) int *pVar; == int* pVar;
- 포인터 변수에 저장된 메모리 주소로 접근한 메모리 영역의 데이터(값)을 의미
포인터 선언 과 데이터 형
- 선언 형식
- 데이터형 *변수명 = int *pPtr;
- 데이터형에 따른 의미
구분 | 의미 |
char * | 문자형 메모리 주소를 저장 |
int * | 정수형 메모리 주소를 저장 |
float * | 실수형 메모리 주소를 저장 |
- 포인터 변수의 선언과 의미
scanf_s 함수의 사용
- & 는 메모리 주소 접근 이므로, 포인터는 메모리 주소를 가지고 있으므로 & 연산자를 쓰지 않는다.
void 형 포인터
- 의미 : 데이터형이 정해지지 않은 포인터 변수
- 역활 : 모든 메모리 주소를 저장만 함.
- 접근을 위한 데이터형 변환 필요
- *(데이터형 *) 포인터명
- 형식 : void *ptr;
포인터 와 배열
- 포인터로 배열을 다룰수 있습니다.
- 이유 : 같은 데이터형, 연속적인 메모리 할당
- 방법 2가지
- 1. 직접 접근 : pPtr + n
- 2. 배열 형식으로 접근 : pPtr[n]..
- 직접 접근법
- 포인터 변수 + n 와 *( 포인터변수 + n ) 의 의미
- pPtr + 1, pPtr + 2, pPtr +3...: 주소 접근시
- *(pPtr + 1), *(pPtr + 2), *(pPtr + 3)... : 값 접근시
- 포인터 변수 + n 와 *( 포인터변수 + n ) 의 의미
- 배열 형식 접근
- 포인터 변수[n] 의 의미
- pPtr[0] , pPtr[1], pPtr[2]... : 주소 접근시
- *pPtr[0], *pPtr[1], *pPtr[2]... : 값 접근시
- 포인터 변수[n] 의 의미
널 포인터
- 아무것도 참조하지 않는 포인터 변수
- 저장하는 값 : 0, '\0', NULL
- 포인터를 사용하여 할당한 메모리를 해제했을 때
포인터를 활용한 메모리 생성과 해제 (malloc & free)
*void malloc ( size_t size );
- #include <stdlib.h> or <malloc.h> 포함
- size_t : unsigned int 의 축약형 입니다.
- 할당한 메모리 공간이 부족하면 NULL, 0, '\0' 리턴
- 할당한 메모리의 첫번 째 주소를 리턴
- 리턴형이 void * 이므로 형 변환을 통해 메모리 주소를 받아야 합니다.
void free ( void *memblock );
- memblock : 해제할 메모리 주소
- 할당한 메모리는 반드시 해제 해줘야 합니다.
메모리 계산 키워드 sizeof
- 메모리 계산 키워드 sizeof
- 데이터 형, 변수, 배열의 메모리 크기를 바이트 단위로 알려주는 키워드
- 형식
- sizeof ( 변수 또는 데이터형 ), sizeof 변수
- sizeof ( int ), sizeof ( 변수명 ), sizeof ( 배열명 )
int arr[] = { 1,2,3,4,5 };
int nCnt = sizeof(arr) / sizeof(arr[0]);
/*
sizeof(arr)는 전체 arr 바이트 크기
sizeof(arr[0]) 는 arr[0] int type의 크기
두수를 나누면 추후, arr 갯수가 달라져도 같은결과를 얻을수 있으므로 nCnt에 상수값을 바로 대입하는
방법보다 효율적입니다.
*/
포인터를 이용하여 배열을 함수로 전달
- 포인터 자체는 주소값만 가지고 있으므로 배열의 갯수는 별개로 전달해줘야합니다.
int main() {
int* pPtr;
pPtr = (int*)malloc(sizeof(int) * 5);
for (int i = 0; i < 5; i++) {
pPtr[i] = 3;
printf("malloc value %p, %d\n", &pPtr[i], pPtr[i]);
}
printf("before free %p\n", pPtr);
free(pPtr);
printf("after free %p\n", pPtr);
_getch(); //waiting for step
return 0;
}
문자열 다루기
- 배열 에서 문자열 다루기
- read / write 수정이 가능함
- 포인터에서 문자열 다루기
- read 전용
int main() {
char str[10] = "abcedfg";
printf("%s \n", str); //출력 abcdedfg
str[0] = 'z'; //변경 가능
printf("%s \n", str); //출력 zbcdedfg
char* pStr = "abcedfg";
printf("%s \n", pStr);//출력 abcdedfg
pStr[0] = "z"; //오류 발생
printf("%s \n", pStr);
_getch(); //waiting for step
return 0;
}
정리
- & 변수는 변수의 메모리 주소를 의미하듯, *포인터는 메모리 주소로 접근(참조)한 값을 의미합니다.
- 변경되지 않는 문자열을 다룰때 편리합니다.
- 다음 예시를 잘 보면 접근을 어떻게 해야하는지 이해가 됩니다.
char str[] = "C Point example";
char* ptr = &str[0]; //배열에 첫번째 주소를 넘겨 줍니다.
cout << ptr << endl; // ptr 이렇게 하면 다 읽어온다.
//출력 : C Point example
cout << *ptr << endl; // ptr 접근한 값 하나, *ptr ++ 주소값 증가시, 다음값 읽어옴.
//출력 : C
cout << ptr[index] << endl; // ptr[index] 접근한 값 하나, index++ 증가시, 다음값 읽어옴.
//출력 : C
'컴퓨터 언어 > C' 카테고리의 다른 글
[C] C언어 7일차 구조체와 TypeDef (0) | 2020.03.16 |
---|---|
[C] C언어 7일차 포인터2 (0) | 2020.03.16 |
[C] C언어 5일차 배열 (0) | 2020.03.14 |
[C] C언어 4일차 함수 (0) | 2020.03.13 |
[C] C언어 3일차 반복문과 분기문 (0) | 2020.03.12 |