C 프로그래밍 · 2 min read · Nov 20, 2025
리눅스 C 프로그래밍 튜토리얼 21부: 문자 포인터, 포인터 배열 및 포인터의 포인터

포인터의 개념은 C 프로그래밍 언어에서 매우 중요한 개념 중 하나입니다. 지금까지 우리는 C에서 포인터의 여러 측면에 대해 논의했습니다. 이를 확장하여 이번 튜토리얼에서는 몇 가지 더 포인터 개념에 대해 논의할 것입니다.
C에서의 문자 포인터, 포인터 배열 및 포인터의 포인터
다음 코드 줄을 사용하여 문자 포인터부터 시작하겠습니다:
char p[] = "I like HowtoForge"
char *p = "I like HowToForge"첫 번째 줄은 큰따옴표 안의 문자 수와 같은 크기의 배열 ‘p’를 정의합니다. 그러나 다음 줄은 문자열 상수를 가리키는 포인터 ‘p’를 정의합니다.
여기서의 차이점은 첫 번째 ‘p’가 배열이기 때문에 배열의 내용을 쉽게 수정하거나 변경할 수 있다는 것입니다. 그러나 두 번째 ‘p’는 문자열 상수를 가리키고 있으므로 문자열 내용을 변경할 수 없습니다.
예를 들어, 다음 코드는 문자열 상수를 수정하려고 시도합니다:
#include
int main()
{
char *p = "I like HowToForge";
p[0] = 'U';
return 0;
} 그리고 이 코드가 내 시스템에서 생성한 출력은 다음과 같습니다:
Segmentation fault이 오류는 프로그램 실행이 갑자기 종료되었음을 나타내며, 이는 우리가 상수인 것을 변경하려고 시도했기 때문입니다.
또한 포인터 ‘p’가 다른 문자열을 가리키도록 만들 수 있지만, 배열 ‘p’의 기본 주소는 변경할 수 없다는 점을 기억하세요(이 점은 이전 튜토리얼 중 하나에서 이미 논의한 바 있습니다).
이제 포인터 배열로 넘어가겠습니다. 정수, 문자 및 기타 유형의 배열을 본 것처럼 포인터 배열도 있을 수 있습니다. 예를 들어, 다음 프로그램은 정수 포인터의 배열 ‘arr’를 정의하고 여기에 값을 할당합니다.
#include
int main()
{
int *arr[3];
int a = 0, b = 1, c = 2;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
return 0;
} 배열에 할당된 값은 주소라는 점에 유의하세요. 이는 ‘arr’이 포인터의 배열이기 때문이며, 포인터는 주소 외에는 아무것도 저장하지 않습니다. 이제 이러한 주소에 저장된 값을 액세스하려면 * 연산자를 사용해야 합니다.
다음 예제(이전 예제의 확장에 불과함)는 이를 보여줍니다:
#include
int main()
{
int *arr[3];
int a = 0, b = 1, c = 2;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
for(int i=0; i < 3; i++)
printf("\n arr[%d] is: %d",i,*(arr[i]));
return 0;
} 출력은 다음과 같습니다:
arr[0] is: 0
arr[1] is: 1
arr[2] is: 2 정수 포인터 배열(여기서 논의한 것과 같은)과 유사하게, 문자 포인터 및 기타를 저장하는 배열도 가질 수 있습니다.
이제 포인터의 포인터로 넘어가겠습니다. 지금까지 여러 번 반복했듯이, 포인터는 주소를 저장합니다. 지금까지 진행된 C 프로그래밍 튜토리얼 시리즈에서는 포인터가 비포인터 변수를 가리키는 것만 보았지만, 사실 포인터는 다른 포인터를 가리킬 수도 있습니다.
즉, 포인터는 다른 포인터의 주소를 저장할 수 있습니다. 예를 들어, 다음은 이중 포인터 또는 포인터의 포인터입니다:
int **ptr;다음은 이중 포인터를 활용한 코드입니다:
#include
int main()
{
int *ptr;
int p;
int a = 10;
ptr = &a;
p = &ptr;
printf("\n Pointer 'p' points to pointer 'ptr' which further points to value: %d", p);
return 0;
} 출력은 다음과 같습니다:
Pointer 'p' points to pointer 'ptr' which further points to value: 10이것이 이중 포인터의 예입니다. 유사한 방식으로 포인터의 포인터의 포인터를 가질 수 있으며, 예를 들어 int *ptr로 정의됩니다. 이러한 ‘포인터의 포인터의 포인터……’ 수준의 최대 수는 구현에 따라 다릅니다(경우에 따라 제한이 12인 경우도 있습니다).
실제로는 포인터의 포인터는 최대 3단계까지 만나는 경우가 많으며, 더 많은 단계가 있으면 논리가 이해하고 유지하기 더 복잡해집니다.
결론
우리는 여기에서 세 가지 중요한 포인터 관련 개념을 논의했습니다. 여기서 논의한 예제와 개념을 시스템에서 시도하여 이러한 것들이 어떻게 작동하는지에 대한 더 나은 아이디어를 얻는 것이 좋습니다. 의문이나 질문이 있는 경우 아래에 댓글을 남겨주세요.
새 게시물을 받은 편지함에서 받기
스팸은 없습니다. 언제든지 구독 해지 가능합니다.