일반적인 포인터 사용
일반적인 포인터 사용
Understanding and Using C Pointers: Core Techniques for Memory Management 1st Edition을 읽고 정리한 내용을 기술합니다.
Understanding and Using C Pointers 정리 시리즈
일반적인 포인터 사용
포인터는 매우 다양한 방법으로 사용된다. 이번 포스팅에서는 다음을 포함한 포인터의 다양한 사용법에 대해서 다룬다.
- 다중 수준 간접지정
- 상수 포인터(중요)
다중 수준 간접지정
포인터는 다중 수준 간접지정(indirection)을 이용할 수 있다. 어떤 변수가 포인터에 대한 포인터로 선언된 경우를 흔하게 볼 수 있는데, 이를 이중 포인터(double pointer) 라고 부르기도 한다. 이중 포인터에 대한 좋은 예는 main 함수에 전통적인 argc와 argv 매개변수를 통해 프로그램 실행 인자가 전달되는 것이다. 이에 대해서는 추후 포스팅에서 다룬다.
예제
#include <stdio.h>
int main() {
char* titles[] = {"A Tale of Two Cities",
"Wuthering Heights",
"Don Quixote",
"Odyssey",
"Moby-Dick",
"Hamlet",
"Gulliver's Travels"};
// bestBooks, englishBooks
char **bestBooks[3];
char **englishBooks[4];
bestBooks[0] = &titles[0];
bestBooks[1] = &titles[3];
bestBooks[2] = &titles[5];
englishBooks[0] = &titles[0];
englishBooks[1] = &titles[1];
englishBooks[2] = &titles[5];
englishBooks[3] = &titles[6];
printf("%s\n", *englishBooks[1]); // Wuthering Heights 출력
return 0;
}
bestBooks
와 englishBooks
배열은 titles
배열에서 책 제목을 복사하여 가지는 것보다
titles
배열에서 해당 책 제목의 주소를 포함하려고 한다.
이 방법의 결과 각각의 책 제목에 대한 메모리 복사를 피할 수 있으며 책 제목이 한 곳에만 위치하게 된다.
bestBooks[idx]
및 englishBooks[idx]
의 각 인덱스 주소공간에는 char*
의 주소를 가지게 된다.
따라서 printf
문에서는 해당 주소를 가진 포인터의 역참조(*
)를 통해 책 제목을 가져올 수 있다.
상수와 포인터
영어 서적과 달리 한국에서는 상수 포인터, 포인터 상수 간의 혼용이 있는 것 같다…
일단 이번 포스팅에서는 포인터가 가리키는 주소에 있는 값을 변경하지 못하게 막는 것을 상수 포인터로, 포인터가 가리키는 주소를 변경하지 못하게 막는 것을 포인터 상수라고 하겠다.
본 서적에서는 각각을 상수에 대한 포인터, 상수 포인터로 칭한다. << 이렇게 외우는게 좋을 듯
예제 코드
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int* ptr = arr; // HERE
*ptr = 10;
printf("%d ", *ptr);
ptr++;
printf("%d ", *ptr);
return 0;
}
// 결과 : 10 2
위 코드에서 HERE 주석이 되어있는 line은 아무런 상수 표시가 되어있지 않다.
포인터가 가리키는 주소 : 바꿀 수 있음
포인터가 가리키는 주소의 값 : 바꿀 수 있음
상수 포인터의 경우
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
const int* ptr = arr; // 상수 포인터 : 포인터가 가리키는 주소의 값을 변경할 수 없음
// int const *ptr = arr 도 똑같음!!!!!
*ptr = 10; // error! : 포인터가 가리키는 주소의 값을 변경할 수 없음
printf("%d ", *ptr);
ptr++; // 주소 자체의 변경은 가능.
printf("%d ", *ptr);
return 0;
}
(상수(const) 이후에 포인터(*)가 오니 상수 포인터로 암기해도 될듯?)
포인터가 가리키는 주소 : 바꿀 수 있음
포인터가 가리키는 주소의 값 : 바꿀 수 없음
포인터 상수의 경우
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int* const ptr = arr; // 포인터 상수 : 포인터가 가리키는 주소를 변경할 수 없음
*ptr = 10; // 주소가 가리키는 값의 변경은 가능.
printf("%d ", *ptr);
ptr++; // error! : 주소 자체의 변경 불가능!!
printf("%d ", *ptr);
return 0;
}
포인터가 가리키는 주소 : 바꿀 수 없음
포인터가 가리키는 주소의 값 : 바꿀 수 있음
둘 다인 경우
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
const int* const ptr = arr; // 상수 포인터 : 포인터가 가리키는 주소는 물론 주소의 값도 변경할 수 없음
*ptr = 10; // error! : 포인터가 가리키는 주소의 값을 변경할 수 없음
printf("%d ", *ptr);
ptr++; // error! : 포인터가 가리키는 주소를 변경할 수 없음
printf("%d ", *ptr);
return 0;
}
포인터가 가리키는 주소 : 바꿀 수 없음
포인터가 가리키는 주소의 값 : 바꿀 수 없음