반응형

C언어를 배우는 많은 사람들이 이 포인터(Pointer)때문에 C언어 배우기를 포기하는 경우가 가장 많다고 합니다. 다른 언어에서는 보기 쉽지 않은 기능입니다. 사실, java의 경우는 premitive type(boolean, byte, char, int, long, float, double)을 제외한 모든 type은 암묵적으로 포인터 변수입니다. 다만 C언어는 명시적 포인터를 사용한다는 것만 다름에도 불구하고, 많은 개발자들이 C언어를 포인터때문에 가장 어려워하고 포기하게 됩니다.

 

포인터 변수는 메모리 주소를 저장하는 변수 또는 메모리 주소를 가리키는 변수를 말합니다.

 

Pointer 변수 선언 방법

type *변수명;

type *변수명 = 다른변수의 주소;

포인터 변수는 일반변수를 선언하듯이 하면서 type 다음에 *를 붙여서 선언합니다. 사용 시에는 꺼꾸로 변수앞에 *을 붙이면 저장된 데이터의 type이 됩니다. (아래 설명)

 

예). int 변수와 int 포인터 변수

int  value = 100;
int *ptr   = &value;

 

C언어의 변수는 그 변수의 type에 맞는 데이터를 저장할 공간(byte수)을 가지고 있으며, 변수는 메모리 상에 특정 위치를 가지고 있습니다. (메모리상의 위치를 주소, 또는 번지라고 합니다.)

위의 예에서 value 변수 이름은 100이라는 값을 뜻합니다. 그러면 변수가 실제로 위치하고 있는 주소는 어떻게 알 수 있을까요? 그것은 &(주소 연산자)를 변수 앞에 붙여서 얻을 수 있습니다.

 

value가 int 타입의 데이터를 저장하듯이, 위의 ptr 변수는 int * 타입의 데이터를 저장하는 변수입니다. int * 타입은 int형의 데이터가 저장된 변수의 주소 타입입니다.

 

따라서, value가 정수값을 대입하듯이 ptr은 int 변수의 주소, 즉, &value를 대입할 수 있습니다.

 

 

예). 일반 변수와 포인터 변수와 관련 예제

int  value = 100;
int *ptr   = &value;

printf("value  = %d\n", value);
printf("&value = %p\n", &value);
printf("ptr    = %p\n", ptr);
printf("*ptr   = %d\n", *ptr);
printf("&ptr   = %p\n", &ptr);

결과)
value  = 100
&value = 0x7ffd3cf1aa54
ptr    = 0x7ffd3cf1aa54
*ptr   = 100
&ptr   = 0x7ffd3cf1aa58

위의 예제에서

value의 값은 100.

value의 메모리 주소(&value)는 0x7ffd3cf1aa54 (메모리 번지는 실행할 때마다 다를 수 있음)입니다.

ptr은 정수의 데이터가 저장된 주소를 저장할 수 있으므로, &value를 저장하였으므로 ptr의 값은 &value와 같은 값입니다.

ptr은 데이터가 저장된 주소이므로 그 주소에 저장된 데이터는 무엇인지를 아는 방법은 무엇이지?

바로 그것은 포인터 변수에 *를 붙이면, 즉, *ptr이 그 번지에 저장된 데이터를 뜻합니다.

 

변수를 선언할 때에, int *ptr; 이라고 했을 때에는 ptr이 포인터 변수라는 의미이며,

int *ptr에서 *ptr하면 남는 부분은 앞에 있는 int가 됩니다. 즉, *ptr이 int 타입이라는 뜻과 같습니다. 그래서 *ptr하면 ptr이 저장된 번지에 저장된 값이 되는 것입니다. 위의 경우 *ptr은 value의 주소에 저장된 값, 즉, 100이 됩니다.

 

그리고 ptr은 자체도 변수이므로 별도의 번지를 가지게 됩니다. 따라서 ptr 자체의 주소를 얻으려면 변수에 주소 연산자(&)를 앞에 붙여서 표시를 합니다. 위의 예에서 ptr의 주소 &ptr은 0x7ffd3cf1aa58 (실행할 때마다 다를 수 있음)이 됩니다.

 

위의 예제와 결과에 대해서는 꼭 이해를 해야만 합니다.

 

 

예). 일반 변수와 포인터 변수간의 데이터 공유

int  value = 100;
int *ptr   = &value;

printf("value  = %d\n", value);
printf("*ptr   = %d\n", *ptr);

*ptr = 200;
printf("value  = %d\n", value);
printf("*ptr   = %d\n", *ptr);


value = 300;
printf("value  = %d\n", value);
printf("*ptr   = %d\n", *ptr);

결과)
value  = 100
*ptr   = 100

value  = 200
*ptr   = 200

value  = 300
*ptr   = 300

포인터 변수 ptr은 메모리의 번지수를 저장하고 있으므로 value의 값이 변경되면, ptr이 저장하고 있는 주소의 값인 *ptr도 함께 변경됩니다.

마찬가지로 *ptr = 200 처럼 그 주소에 값을 변경하면 value의 값도 바뀝니다.

 

이와 같이 포인터 변수는 데이터부를 직접 가지고 있지 않고 그 데이터가 저장된 위치를 가지고 있음으로써 데이터의 동기화를 할 수 있습니다.

 

지금까지 설명으로는 포인터 변수에 대한 개념을 설명하였습니다. 아직은 포인터 변수가 왜 필요한 지 이해할 수 없을 것입니다. 그냥 value를 가지고 작업하면 될텐데 뭐할려고 어려운 포인터를 사용해.... (지금까지는 맞습니다.)

 

향후에 동적 메모리 할당, 함수의 호출 시에 포인터 사용 등에 대해서 할 예정입니다만, 위의 예제처럼 단순히 다른 일반 변수의 주소를 가지고 사용하는 경우는 많지 않습니다.

 

위의 예제처럼 다른 변수의 주소를 굳이 저장해서 작업을 하는 것이 편리한 경우에 대해서 예를들도록 하겠습니다.

 

업무 처리 변수 3개가 있습니다. 로직은 같은 데, 옵션에 의해서 3개의 변수 중에 하나의 변수에 대해서 집중적으로 작업을 해야 하는 경우가 있다고 가정해봅니다.

int  value1 = 0;
int  value2 = 0;
int  value3 = 0;
int  option;

...

if(option == 1)
   value1 += 4;
else if(option == 2)
   value2 += 4;
else if(option == 3)
   value3 += 4;

.... 로직 계속

if(option == 1 && value1 > 4) {
   ...
} else if(option == 2 && value2 > 4) {
   ...
} else if(option == 3 && value3 > 4) {
   ...
}

의 경우

int  value1 = 0;
int  value2 = 0;
int  value3 = 0;
int  *value;
int  option;

...

if(option == 1)
   value = &value1;
else if(option == 2)
   value = &value2;
else if(option == 3)
   value = &value3;

*value += 4;

.... 로직 계속

if(*value > 4) {
   ...
}

처럼 option에 의해서 value에 해당 변수의 주소를 대입해서 사용함으로써 같은 로직의 처리를 할 수 있습니다.

 

 

아직, 포인터에 대해서 제대로 시작도 안했습니다만, 여기까지 정리를 하자면... (int 변수를 기준으로)

 

int *ptr; 
은 int 데이터를 저장하고 있는 주소를 저장하는 변수임을 선언합니다. (포인터 변수의 선언)
int *ptr = &value;
또는
ptr = &value;  

포인터 변수 선언과 함께 다른 변수의 주소를 초기화하거나, 포인터 변수에 대입을 할 수 있습니다.
포인터 변수에 주소를 대입시에는 ptr 앞에 *를 붙이지 않습니다.
*ptr
은 ptr이 저장하고 있는 주소에 저장된 값을 뜻합니다. *는 간접 참조 연산자
int *ptr로 선언했으므로 *ptr 부분을 모두 뺴고 나면 int가 되므로 *ptr은 저장된 값이 됩니다.
int value;
int *ptr;
ptr = &value;
*ptr = 200;
ptr이 가리키고 있는 주소에 저장된 값을 바꾸면 value의 값도 함께 변경되며 
반대로 value의 값을 바꾸면 *ptr의 값도 변경됩니다.

 

 

 

 

 

C Programming Language 문법

1. C 프로그래밍 언어는? 2. C언어 개발 환경 (실습 환경) 3. C언어의 컴파일 과정 4. C 소스 파일 구성 5. 주석문(Comment) 6. 식별자 명명 규칙 7. C 프로그래밍의 시작 - 함수 8. 변수와 상수 (정수형) 9. 변..

www.it-note.kr

 

반응형

'C언어 > 문법' 카테고리의 다른 글

21. 포인터(Pointer) - 동적 메모리 할당  (0) 2019.11.26
20. 포인터(Pointer) - Call by value와 Call by Reference  (4) 2019.11.23
18. 배열 (配列: array)  (0) 2019.11.06
17. 반복문 (do ~ while)  (0) 2019.11.04
16. 반복문 (while)  (2) 2019.11.04
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,