'&'
int '*'
int* num_address
- 주소를 따라가면 int형 자료가 있다는 뜻
- 코딩 표준은
int* 변수
반환형으로서의 포인터
지역변수 포인터 반환 -> 댕글링포인터 유발
int* func(const int op1, const int op2);
- 지역 변수의 주소를 반환: 매우 위험
- 당연히.. 지역변수는 스택메모리! 함수 호출이 끝나면 유효한 메모리가 아니다.
- 유효하지 않은 포인터 = 댕글링포인터
반환형 포인터 되는 경우
- 전역 변수
- 파일속 static 전역 변수
- 함수내 static 변수
- 힙 메모리에 생성한 데이터
즉, 함수 스택프레임에 들어가지 않으면 괜찮다.
NULL 포인터 문제점
매개변수 편
- 함수 매개변수로 NULL이 안들어온다고 가정하고 함수 작성할 것
- NULL이 들어올 수 있는 함수는 매개변수명에서 분명히 밝힐 것
- 함수의 매개변수가 NULL 포인터를 허용한다면, 매개변수 이름 끝에
'_or_null
을 붙인다.
- NULL이 안 들어온다고 가정한 경우
assert()
를 사용해 검증
#include <assert.h>
#define PRICE (2)
void increase_price(int* current_price)
{
assert(current_price != NULL);
*current_price += PRICE;
}
반환값 편
- NULL을 반환해야 한다면 함수 이름에 NULL을 반환하는 것을 명시할 것
NULL 언제 사용하나?
- 포인터 변수를 초기화하고 싶을 때
void do_somthing(void)
{
int* ptr = NULL;
ptr = &g_monster_count;
}
- 포인터 변수가 유효한 주소를 참조하고 있는지 확인하고 싶을 때
- 댕글링 포인터를 막기위해
- 동적 메모리 할당된 메모리
free
후, 포인터 변수는 NULL
!을 이용해 리셋
포인터의 크기
- 모든 포인터는 동일한 크기를 가진다.
- 포인터 크기 = 시스템 아키텍처에 따라 결정
- CPU가 한번에 처리할 수 있는 데이터의 크기 = word
- 32bit arch = 4Byte
- 64bit arch = 8Byte
- 다 같은 크기면 왜
int*
, char*
나눈 건가?
- 위에서도 설명했겠지만,
int*
=> 주소를 따라가면 int형 자료가 있다는 뜻
포인터에 배열을 넣어도 배열크기 나오지 않는다.
포인터 연산
- 포인터에 정수
1
을 더하다.1 * sizeof(int) Byte가 더해짐
short *
라면?
- 2Byte씩 증가 = +1 * sizeof(short)
- 억지로 1Byte만 옮기려면
- (char*)로 캐스팅
포인터 용도
많은(큰) 데이터 매개변수
- 배열이 매개변수로 전달될 때, 첫 번째 요소의 주소가 전달이 될 뿐 링크
반환 값이 둘 이상일 때
동적 메모리 할당
포인터 배열
- 물론 링크 처럼, 포인터에 배열을 할당해도, sizeof()로 배열 크기가 구해지지 않는다.
함수로 활용
- 링크: 배열을 함수 매개변수로 전달햇을 때, 사실은 배열의 첫번째 포인터가 전달되는 것
- 링크: 배열을 함수 매개변수로 전달했을 때, 왜
sizeof()
로 봤을 때 다른가?
- +) 포인터 배열내에는 각 내부 배열의 idx를 모르기 때문에 전달해주어야한다.