컴퓨터 프로그래밍/C

C언어 포인터(Ponter) / 다중 포인터

나노콛 2019. 7. 23. 10:54

포인터란
메모리 공간을 가리키는 주솟값을 뜻합니다.

포인터 변수란
메모리 공간을 가리키는 주솟값을 저장하는 공간입니다.

 

/*별표의 위치는 상관없다 */
int* p1;
char * p2;
void *p3;

포인터 변수의 저장공간은 자료형에 상관없이
컴퓨터 os 주소체계를 따르는데요
32bit 운영체제 이면 포인터 변수의 공간이 4바이트고
64bit 운영체제 면 8바이트입니다.

포인터 변수를 선언할 때 자료형이 각각 정해져 있는 이유는
자료형 저장 크기만큼 읽어오기 위해서이며
자료형마다 저장되는 자료가 쓰이는 형식이 틀린 이유이기도 합니다.
자료형의 크기만 고려했다면 가장 큰 자료형 포인터 변수로 만들면 되는데
자료형마다 저장되는 자료가 메모리에 쓰이는 형식이 다르기 때문에 그렇습니다.

void형은 형태가 정해져 있지 않는 자료형인데
이 자료형을 사용할때는 캐스팅을 이용해서 사용할 자료형을 지정하면 사용할 수 있습니다.


주소 연산자 / 역참조 연산자

 

#include <stdio.h>

int main()
{
	int a = 1;
	int b = 2;
	char c = 'z';

	int* pA;
	int* pB;
	char* pC;

	pA = &a; //포인터 변수 pA에 a의 주소를 담는다.
	pB = &b;
	pC = &c;

	printf("pA : 0x%008x\n", pA); //pA에는 a의 주소값이 담겨있다.
	printf("pB : 0x%008x\n", pB);
	printf("pC : 0x%008x\n", pC);

	printf("pA : %d\n", *pA);// 역참조 연산자로 pA가 가리키고 있는 a의 값을 확인한다.
	printf("pB : %d\n", *pB);
	printf("pC : %c\n", *pC);
	return 0;
}

포인터에서 헷갈리는 부분은 
왜 사용하는지에 대한 의문이 계속 남아 있기 때문에 헷갈립니다.

해당 함수 안에서 만든 변수가 내부가 아닌 
외부의 함수나 외부의 공간에서 사용할 수 있고
자료구조에서 포인터가 쓰이기 때문인데요

일단은 외부 함수에서 쓰기 위해 포인터를 쓴다는 점을 생각을 해 두시고

하나씩 확인해보겠습니다.

 

	int a = 1;
	int b = 2;
	char c = 'z';

	int* pA;
	int* pB;
	char* pC;

일반 변수를 선언 초기화하고
해당 변수의 주소를 담을 포인터 변수를 생성합니다.

 

pA = &a; //a의 주소가 1000이라면 pA에는 1000
pB = &b;
pC = &c;

포인터 변수에 각각 일반 변수의 주솟값을 담습니다.

이 순간 각각의 포인트 변수에는 해당 일반 변수의 주솟값이 들어가 있습니다.

printf("pA : 0x%008x\n", pA); //pA에는 a의 주소값이 담겨있다.
printf("pB : 0x%008x\n", pB); //%x는 16진수 출력 서식문자
printf("pC : 0x%008x\n", pC); //%008은 출력되는값을 8자리로 마추고 빈자리는 0으로 채움

pA에는 a의 주솟값 1000이 들어가 있습니다.
그래서 출력하면 a의 주솟값이 출력이 됩니다.

 

printf("pA : %d\n", *pA);// 역참조 연산자로 pA가 가리키고 있는 a의 값을 확인한다.
printf("pB : %d\n", *pB);
printf("pC : %c\n", *pC);

선언할 때의 *이 아닌 포인터 변수 앞에 붙은 *은 역참조 연산자입니다.
역참조 연산자는 주소가 가리키고 있는 값을 의미합니다.

pA가 가리키고 있는 a의 주소(1000)의 값 1입니다.

 


다중 포인터

 

int a;
int* pA;
int** ppA;
int*** pppA;

pA = &a;
ppA = &pA;
pppA = &ppA;

보통은 **까지만 사용되고 ***는 거의 보기 어렵다고 보시면 됩니다.


int* pA는 일반 변수 a의 주솟값을 담습니다.

int** ppA는 포인터 변수 pA의 주솟값을 담습니다.

int*** pppA는 포인터 변수 ppA의 주솟값을 담습니다.

결국 모두 일반 변수 a를 가리키고 있는 형태가 나옵니다.

다중 포인터는 아래 소스가 이해가 되면 된다고 보시면 됩니다.

 

#include <stdio.h>

void SwapIntPtr(int **p1, int **p2)
{
	int * temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main(void)
{
	int num1 = 10, num2 = 20;
	int *ptr1, *ptr2;
	ptr1 = &num1, ptr2 = &num2;
	printf("*ptr1, *ptr2: %d %d \n", *ptr1, *ptr2);

	SwapIntPtr(&ptr1, &ptr2);
	printf("*ptr1, *ptr2: %d %d \n", *ptr1, *ptr2);
	return 0;
}

위 소스의 전제조건은
ptr1의 "주소" ptr2의 "주소"를 변경하여
값을 스왑하는 형태로 되어있습니다.

728x90