어려운 C언어 포인터 예제 4개로 마스터하기

포인터는 C언어 핵심이라고 해도 과언이 아닙니다. 이 포스트에서는 C언어의 꽃! 포인터란 무엇인지 간단하고, 담백하게 설명하고자 합니다.


포인터는 어렵다


C언어를 처음 배우는 많은 사람이 포인터를 싫어합니다. C언어 포인터 개념은 한 번 이해하면 매우 간단하지만, 모르면 무슨 말을 하는지 이해할 수 없습니다.


왜 이해하기 어려우냐면, 포인터는 실체를 갖는 것이 아니라 실체를 나타내는 선만 갖고 있기 때문입니다.


포인터의 개념을 기억하면 다른 언어를 이해하는 데에도 분명 유용합니다. 예를 들어 JavaScript 또는 Perl에도 포인터와 비슷한 개념이 존재합니다.


처음에는 몰라도 다양한 샘플을 겪다 보면 몸으로 기억할 수 있습니다. 누구나 C언어 포인터 이해할 수 있으니 어렵다고 포기하지 말고 노력하세요. 욕은 해도 좋습니다.

포인터는 주소를 저장하는 변수


C언어 포인터는 주소를 기억하기 위한 변수입니다.


컴퓨터는 메모리에 정보를 쓰고 사용합니다. 예를 들어, char형으로 선언된 배열, int 변수, 함수조차도 프로그램 동작시 모두 메모리에 할당됩니다. 메모리 중 어디에 있는지를 보여주기 위한 것이 포인터입니다.


아마도 무슨 말인지 모르겠다는 분들이 있을 것 같아 샘플 소스 코드 소개하고 설명하겠습니다.


[샘플 1]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
int main()
{
    char a[8];
    char *ptr;
 
    a[0= 'a';
    a[1= 'b';
    a[2= 'c';
    a[3= 'd';
    a[4= 'e';
    a[5= 'f';
    a[6= 'g';
    a[7= '\0';
 
    ptr = a;
    printf("%c\n"*ptr);
 
    ptr = ptr + 3;
    printf("%c\n"*ptr);
 
    return 0;
}
cs



위 예제를 실행하면 "a"와 "d"라는 문자가 출력됩니다.


위 예제 프로그램은 먼저 7개의 문자와 종료 문자까지 포함한 8개 크기 배열(문자열)을 선언했습니다. 그 후 char형 포인터를 선언했습니다. 포인터형에는 "*"를 붙입니다.


위 예제는 ptr이라는 char형 포인터에 배열 a의 시작 주소를 할당합니다. 그리고 첫 번째 printf 함수는 ptr이 나타내는 주소의 끝인 종료 문자까지 표시합니다. C언어 포인터 변수 앞에 "*"를 쓰면 포인터가 가리키는 주소에 포함된 내용을 의미합니다.


다음, ptr에 3을 더합니다. ptr에 3을 더하는 것은 ptr이 가리키는 주소를 3번지 만큼 이동한다는 의미입니다. 위 예제에서는 먼저 배열 a의 주소를 ptr에 대입했으므로 ptr 위치 3개를 이동하여 a[3]인 'd'를 가리키는 것입니다.


따라서 *ptr의 내용을 표시하는 두 번째 printf는 "d"라는 결과를 표시합니다.



Pointer는 화살표. 보유한 게 아니라 보유한 곳을 가리키는 이정표.Pointer는 화살표. 보유한 게 아니라 보유한 곳을 가리키는 이정표.


[샘플 2]


이번에는 ptr이 가리키는 내용을 변경해 보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
 
int main()
{
    char a[8];
    char *ptr;
    int i;
 
    a[0= 'a';
    a[1= 'b';
    a[2= 'c';
    a[3= 'd';
    a[4= 'e';
    a[5= 'f';
    a[6= 'g';
    a[7= '\0';
 
    ptr = a;
    *ptr = 'Z';
 
    ptr += 3;
    *ptr = 'W';
 
    printf("%s\n", a);
 
    return 0;
}
cs



위 예제 출력 결과는 어떨까요?


위 예제를 실행하면 문자열 a의 글자 번째와 네 번째 문자가 변경됩니다.


문자열 a의 내용은 포인터 변수 ptr을 통해 변경됩니다. 처음에는 ptr이 a의 시작을 보여줍니다. ptr이 a의 시작을 나타내고 있을 때 "Z"라는 문자가 *ptr에 대입됨에 따라, a의 첫 번째 문자는 "a"에서 "Z"로 변경됩니다.


마찬가지로 4번째 문자도 "d"에서 "W"로 변경됩니다.


이처럼 C언어 포인터를 사용하여 포인터가 가리키는 데이터를 변경할 수 있습니다.

int형 포인터


C언어 포인터의 이해를 돕기 위해 int형 포인터를 다룹니다.


[샘플 3]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int a = 1;
    int *ptr;
 
    ptr = &a;
 
    *ptr = 128;
 
    printf("%d\n", a);
 
    return 0;
}
cs



위 예제를 실행하면 '1'이 아니라 '128'이라는 문자가 표시됩니다.


위 예제 프로그램에서는 먼저 변수 'a'를 선언하며 1로 초기화합니다. 이후 프로그램에선 a 변수에 대한 직접적인 변경은 시도하지 않습니다.


int형 포인터 변수 "ptr"에 변수 "a" 주소를 할당합니다. 그 후, "*ptr"에 "128"이라는 값을 할당합니다. 포인터 변수 앞에 '*'를 쓰면, "포인터가 가리키는 주소"라는 뜻입니다.


따라서 "a"의 주소를 나타냅니다. ptr이 가리키는 대상이라고 하면 "*ptr을 통해 변수 a에 기록한다"라고 이해할 수 있습니다.


C언어 아버지 - 데니스 리치C언어 아버지 - 데니스 리치


함수 포인터


[샘플 4]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
void func()
{
    printf("function\n");
}
 
int main()
{
    void (*ptr)();
 
    ptr = &func;
 
    (*ptr)();
 
    return 0;
}
cs



위 예제를 실행하면 "function"이라는 문자열이 출력됩니다.


위 프로그램에서 함수 포인터 "ptr"을 선언합니다. 함수 포인터에 "func"라는 함수 포인터를 대입합니다. 그리고 "*ptr"을 이용하여 "ptr"이 가리키는 func()를 실행할 수 있습니다.


함수에 포인터가 있어? 라고 생각하실 수 있습니다. 하지만, 변수뿐만 아니라 함수 또한 C언어 포인터로 취급할 수 있다는 점 꼭 기억해주시기 바랍니다.


이것으로 C언어 입문에 해당하는 포인터 설명 마칩니다.


C언어와 관련된 더 많은 글은 아래 링크를 참고해주세요.


관련 글

포인터 주소와 포인터의 포인터

https://codingcoding.tistory.com/1107


배열 구조체 포인터 함수 사용 방법

https://codingcoding.tistory.com/1108


if문 기초, 관계연산자, 논리연산자, else if 사용법

https://codingcoding.tistory.com/155


동적 메모리 할당, 배열 메모리 영역 (malloc sizeof 이해)

https://codingcoding.tistory.com/645

댓글(0)

Designed by JB FACTORY