메모리 주소 저장하는 변수
일반 변수: 값 저장
포인터 변수: 값이 있는 위치(주소) 저장
&
(Address-of 연산자)변수의 메모리 주소를 가져옴
int a = 10;
printf("%p\n", &a); // a의 주소 출력
*
(Dereference / Indirection 연산자)포인터가 가리키는 주소의 값에 접근
int a = 10;
int *p = &a; // p는 a의 주소 저장
printf("%d\n", *p); // p가 가리키는 값(a) = 10
*p = 20; // a 값이 20으로 변경됨
&
과 *
의 관계 예제int a = 100;
int *p = &a; // p에 a의 주소 저장 (&)
printf("%d\n", *p); // p가 가리키는 값 출력 (*)
int *ptr; // int형 변수 주소 저장 가능
double *dptr; // double형 변수 주소 저장 가능
char *cptr; // char형 변수 주소 저장 가능
아무것도 가리키지 않는 포인터
int *p = NULL;
if (p == NULL) { /* 주소 없음 */ }
주의사항 | 설명 | 예시 |
---|---|---|
1. 초기화 없이 사용 금지 | 선언만 하고 쓰면 쓰레기 주소 가리킴 → 크래시 | int *p; *p = 10; // ❌ |
2. 해제 후 접근 금지 | free 한 뒤 접근하면 댕글링 포인터 발생 |
free(p); printf("%d", *p); // ❌ |
3. 범위 밖 접근 금지 | 배열이나 할당 메모리 범위 초과 시 메모리 오염 | arr[10] = 5; // ❌ |
4. 형(type) 일치 | 포인터 타입과 실제 데이터 타입 일치 필요 | double *p; int a; p = &a; // ❌ |
5. NULL 체크 | 사용 전 if (p != NULL) 확인 |
if (p) printf("%d", *p); |
6. 이중 포인터 주의 | **pp 는 두 번 역참조하므로 구조 정확히 이해 |
int **pp; |
실행 중(runtime) 에 필요한 만큼 메모리 확보
정적 할당(static)과 달리 크기를 미리 몰라도 가능
C에서는 malloc
, calloc
, realloc
, free
사용
지정한 바이트 크기만큼 메모리 할당
초기화는 하지 않음 (쓰레기값)
int *arr = (int *)malloc(sizeof(int) * 5); // int 5개 공간
지정한 크기만큼 메모리 할당 + 0으로 초기화
쓰레기 치워줌
int *arr = (int *)calloc(5, sizeof(int));
기존 메모리 크기 변경
arr = (int *)realloc(arr, sizeof(int) * 10); // 10개로 확장
동적으로 할당한 메모리 해제
free(arr);
arr = NULL; // 해제 후 NULL로 설정 권장
메모리 할당 후 해제 필요
그렇지 않으면 쓸데 없이 메모리 점유하는 메모리 누수 발생
malloc
의 경우 초기화하거나 하지 않을 경우
이전 데이터 남음
값을 다시 채우기전 (이전 값이 남아있을 때)
그 변수를 사용시 오작동
int *cnt = malloc(sizeof(int));
(*cnt)++; // 초기화 안 했는데 증가 → 예측 불가 결과
항상 먼저 덮어쓰거나 초기화 안할 경우 고려 필요
free
를 통해 메모리 해제시 유의할 점
메모리 공간은 반환되지만 값은 남아 있다
-> 여전히 이전에 할당됐던 주소 가리킴
NULL을 사용 안할 경우:
댕글링 포인터(헤제된 메모리 가리키는 포인터) 발생
다른 데이터 덮어씌워 질 수 있음
조용히 잘 있다가 크래쉬 터짐