zyeon's 작심삼일 코딩 공부
포인터 본문
포인터란 메모리의 주소값을 저장하는 변수를 말하며, 포인터 변수라고도 한다.
주소의 최소 단위는 바이트로, 각 바이트 마다 고유한 주소가 있다.
포인터의 크기는 주소값을 저장하는 변수이기 때문에 같은 플랫폼에서는 자료형에 상관없이 크기가 전부 같다.
32비트 플랫폼에서는 4바이트, 64비트 플랫폼에서는 8바이트 크기를 가진다.
포인터의 자료형에는 전달된 주소에 접근하고 해석하는 방식이 포함되어 있기 때문에 알맞은 포인터 자료형을 사용해야 한다.
만약 int형 포인터를 선언하면 해당 포인터는 4바이트 크기의 접근을 하며, 주소에 저장되어 있는 값의 비트를 int 방식으로 읽는다. 강제 캐스팅을 해서 다른 자료형 변수의 값을 읽어드리게 되면 값이 엄청 커지거나 작아지는 식의 다른 값이 들어 올 수 있다.
int i = 10;
int *p = nullptr; //아무 주소도 가리키지 않음
p = &i; //i의 주소를 가리킴
변수의 주소는 주소연산자(&)로 반환받을 수 있으며, 위 코드처럼 int형 포인터를 선언하면 int형 변수의 주소를 저장해줘야 한다.
포인터를 통해 값을 읽어오거나 변경을 하고싶다면 간접 참조 연산자(*)를 사용하면 된다. 역 참조 연산자라고도 한다.
*p = 20; //i에 20이 들어감
printf("%d \n", i); //20이 출력됨
포인터 p가 가르키는 변수 i를 간접적으로 참조하여 값을 변경해 줄 수 있다.
i의 주소를 가리키고 있는 p의 값을 증가시키면 어떻게 될까?
p += 1; //sizeof(int) 단위로 주소값 증가
포인터가 가리키는 자료형의 크기만큼 주소값이 증가하게 된다. 만약 i의 주소값이 100이었다면, 위 코드를 실행했을 때 i의 주소값은 104가 된다.
int*가 아닌 char* 이었다면 1이 증가해 101이 되었을 것이다.
증감 연산자도 간접 참조 연산자(*)와 같이 사용할 수 있다. 하지만 증감 연산자를 포인터에 적용할 수도 있고, 포인터가 가리키는 대상에 적용할 수도 있기 때문에 주의해서 사용해야 한다.
수식 | 의미 |
v = *p++; | p가 가리키는 값을 v에 대입한 후 p 증가 |
v = (*p)++; | p가 가리키는 값을 v에 대입한 후 p가 가리키는 값 증가 |
v = *++p; | p를 증가시킨 후 p가 가리키는 값을 v에 대입 |
v = ++*p; | p가 가리키는 값을 가져온 후 그 값을 증가하여 v에 대임 |
포인터 사용시 주의할 점
포인터 변수 초기화하기
int *p; //초기화 하지 않고 선언
*p = 100;
초기화를 하지 않고 포인터를 사용하게 되면 포인터가 임의의 주소를 가리키게 된다. 이 때 포인터가 가리키는 곳에 값을 넣으면 다른 정보를 덮어 쓸 수 있으므로 위험하다.
int *p = nullptr;
아무것도 가리키고 있지 않을 때 nullptr를 사용하자. 기존에는 NULL 값을 저장했지만 이는 정수 0을 의미하기 때문에 의도하지 않은 상황이 나올 수 있다.
절대 주소 사용하지 않기
아두이노와 같은 엠베디드 시스템이 아닌 이상, 프로그래머는 절대 주소가 어떤 용도로 사용되는지 모르기 때문이다.
'c++ 정리' 카테고리의 다른 글
const와 포인터 (0) | 2024.06.21 |
---|---|
포인터와 배열 (0) | 2024.06.20 |
지역변수, 전역변수, 정적변수, 외부변수 (2) | 2024.06.14 |
비트 연산자, 플래그 (1) | 2024.06.05 |
자료형 (0) | 2024.06.04 |