본문으로 바로가기

[C언어] 포인터

category C 2014. 5. 14. 23:16

C언어에서 가장 어려워하는 부분이 포인터이다.

 

C언어만이 가지는 가장 강력한 무기이며, 메모리를 직접 엑세스를 하기 때문에 효율적인데 비해, 메모리 누수(Memory Leak)가 포인터 등과 연관되어 나타나기도 하며 처리하기 힘든 버그를 만들기도 한다. 초보자들에게는 양날의 검이 되기도 한다.

 

포인터: 변수의 시작 주소값 + 자료형에 대한 정보

char a;

short b;

int c;

double d;

 

&a: char형인 변수 a의 시작 주소값이다.

&b: short형인 변수 b의 시작 주소값이다.

&c: int형인 변수 c의 시작 주소값이다.

&d: double형인 변수 d의 시작 주소값이다.

 

포인터 변수: 해당 자료형의 주소값을 저장하는 변수, 크기 4bytes

포인터를 저장하는 변수가 포인터 변수라고 생각하면 된다.

포인터라는 말은 대부분  포인터 변수라는 말로 대신 표현 된다.

 

<생각해보기>

1. 왜 크기가 4bytes 일까?

2. 주소값을 저장하기 위해서는 unsigned int 를 쓰면 가능하지 않을까? 

char a;

unsigned int pa = &a; // 컴파일 에러가 나는지 확인해 보세요!

 

포인터 변수 선언

<문법>

자료형* 이름; // *: 포인터 변수 선언의 의미

예>

char* pa;  // char형(1bytes)의 주소값을 저장하는 포인터 변수, 크기 4bytes

short* pb;  // short형(2bytes)의 주소값을 저장하는 포인터 변수, 크기 4bytes

int* pc;   // int형(4bytes)의 주소값을 저장하는 포인터 변수, 크기 4bytes

double* pd;   // double형(8bytes)의 주소값을 저장하는 포인터 변수, 크기 4bytes

void* pv;  // void형의 주소값을 저장하는 포인터 변수, 크기 4bytes

 

자료형 *이름; // 이와 같이 쓸 수도 있다. 그러나 초보들에게는 헷갈라기 쉬운 표현일 수도 있으므로 자료형* 이라고 쓰고 자료형과 *를 묶어서 포인터형이라고 생각하기로 한다.

int a = 1;

int* pa = &a; // 선언과 동시에 초기화

위 문장을 두 문장으로 쓴다면

int* pa;

pa = &a;

이라고 쓸 수 있다. 한줄로 적는 문장에 익숙해 져야 한다.

int a = 1;

int* pa = &a; 

*pa = 2;

printf("%d", a);

//-----------------------

int a = 1;

int

1000번지:&a

a

1

 

int* pa = &a; 

int*

2000번지:&pa

pa

1000

 

*pa = 2;

int

1000번지:&a

a

2

 



 

* 의 또 다른 의미: 포인터변수가 저장하고 있는 곳의 주소값의 내용을 간접 접근(indirect access)한다.

*pa = 2; //뜻은 *(1000번지) : 1000번지의 내용의 간접 접근. 결국은 *pa == a 와 똑같다.

*&a = 3; //뜻은 변수 a의 주소값의 내용물을 말하며, 결국은 *&a == a 와 같다.

 

 

void* 포인터 변수: 어떠한 자료형의 포인터라도 저장할 수 있다는 것이 최대 강점이다 이러한 강점 때문에 다양한 곳에 응용되기도 한다. 그 대신 어떤 자료형인지에 대해서는 알지 못한다. 따라서 내용물 *를 사용해서 주소값의 내용물을 접근할 수 없다.

 

int a = 1;

int* pa = &a; 

*pa = 2;

printf("%d", a);

void* pv;
pv = &a;

//printf("%d\n", *pv); //(x)
printf("%d\n", *((int*)pv)); //(o)

 

<실습1>

#include <stdio.h>
void main()
{

 char a = 'x';
 short b = 1000;
 int c = 123456789;
 float d = 3.14f;
 double e = 1.23456;

 char* pa = &a;
 short* pb = &b;
 int* pc = &c;
 float* pd = &d;
 double* pe = &e;

 printf("a:%c b:%d c:%d d:%g e:%g\n", a, b, c, d, e);
 printf("a:%d b:%d c:%d d:%d e:%d\n",
  sizeof(a), sizeof(b), sizeof(c), sizeof(d), sizeof(e));

 printf("&a:%p &b:%p &c:%p &d:%p &e:%p\n",
  &a, &b, &c, &d, &e);
 printf("pa:%p pb:%p pc:%p pd:%p pe:%p\n",
  pa, pb, pc, pd, pe);

 printf("pa:%d pb:%d pc:%d pd:%d pe:%d\n",
  sizeof(pa), sizeof(pb), sizeof(pc), sizeof(pd), sizeof(pe));
 printf("*pa:%c *pb:%d *pc:%d *pd:%g *pe:%g\n",
  *pa, *pb, *pc, *pd, *pe);

 *pa = 'y';
 *pb = 2000;
 *pc = 987654321;
 *pd = 4.13f;
 *pe = 65432.1;
 printf("*pa:%c *pb:%d *pc:%d *pd:%g *pe:%g\n",
  *pa, *pb, *pc, *pd, *pe);
 printf("a:%c b:%d c:%d d:%g e:%g\n", a, b, c, d, e);
 
 void* pv;
 pv = &a;
 printf("%c\n", a);
 printf("%c\n", *&a);
 //printf("%c\n", *pv); //(x)
 printf("%c\n", *((char*)pv)); //(o)

}

<실습2>

  - 두수를 입력하여 두수를 교환하시오

<실습3>

  - 두수를 입력하여 두수를 교환하시오 (Swap 함수 이용)

<실습4>

  - 두수를 입력하여 두수를 교환하시오 (Swap 함수 이용 + 포인터 이용)

 

이중 포인터 변수: 해당하는 자료형의 포인터 변수의 주소값을 저장하는 변수, 크기 4bytes

한마디로 표현하면 "포인터 변수의 주소값을 저장" 한다. 포인터 변수도 주소값을 가지고 있으며 그 주소값을 저장하기 위한 특별한 변수가 필요하는데 이중 포인터 변수라고 한다.

int a = 1;

int* pa = &a;

int** ppa = &pa;

**ppa = 2;

 

int a = 1;

int

1000번지:&a

a

1

 

int* pa = &a; 

int*

2000번지:&pa

pa

1000

 

int** ppa = &pa; 

int**

3000번지:&ppa

ppa

2000

 

**pa = 2;

int

1000번지:&a

a

2

 

 

 

예제1> 참조만 할 것 (출처:http://www.winapi.co.kr/)

#include <stdio.h>
#include <stdlib.h>
void main()
{
     int len=10,num=5,i;
     char **name;

     name=(char **)malloc(num*sizeof(char *));
     for (i=0;i<num;i++) {
          name[i]=(char *)malloc(len*sizeof(char));
     }

     for (i=0;i<num;i++) {
          sprintf(name[i],"string %d",i);
          puts(name[i]);
     }
     for (i=0;i<num;i++) {
          free(name[i]);
     }
     free(name);
}
예제2> 참조만 할 것 (출처:http://www.winapi.co.kr/)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void InputName(char **pName)
{
     *pName=(char *)malloc(12);
     strcpy(*pName,"Cabin");
}
void main()
{
     char *Name;
     InputName(&Name);
     printf("이름은 %s입니다\n",Name);
     free(Name);
}