본문 바로가기

공부/C언어

(C 예제) 포인터 정리 및 예제

// 예시
void main(void)
{
	int num = 7;
	int *pnum; // 포인터 변수 pnum의 선언
	pnum = # // num의 주소 값을 pnum에 저장
}

정수 7이 저장된 int형 변수 num을 선언하고 이 변수의 주소 값 저장을 위한

포인터 변수 pnum을 선언함.

그리고 pnum에 변수 num의 주소 값을 저장한다.


// 예시
void main(void)
{
	int * pnum1;
	double * pnum2;
	unsigned int * pnum3;
}

int형 포인터 변수 pnum1

double형 포인터 변수 pnum2

unsigned int 포인터 변수 pnum3


// 예시
void main(void)
{
	int num1 = 5;
	int * pnum = &num1;
}

& 연산자는 변수의 주소 값을 반환하므로 상수가 아닌 변수

피연산자이어야 한다.

& 연산자의 반환 값은 포인터 변수에 저장한다.

 

주의) int형 변수 대상의 & 연산의 반환 값은 int형 포인터 변수에

double형 변수 대상의 & 연산의 반환 값은 double형 포인터 변수에 저장해야한다.

일치하지 않으면 안된다.


// 예시
void main(void)
{
	int num = 10;
	int * pnum = # // pnum이 num을 가리킨다.
	*pnum = 20; // pnum이 가리키는 공간에 20 저장
	printf("%d", *pnum); // pnum이 가리키는 공간에 저장된 값을 출력
}
void main(void)
{
	int num1 = 100, num2 = 100;
	int * pnum;

	pnum = &num1; // 포인터 pnum이 num1을 가리킴
	(*pnum) += 30;

	pnum = &num2; // 포인터 pnum이 num2를 가리킴
	(*pnum) -= 30;

	printf("num1:%d, num2:%d \n", num1, num2);
}

pnum의 참조대상을 num1로 해서 30을 증가하고,

참조대상을 num2로 변경해서 30을 감소한다.


주의

위는 ptr이라는 포인터 변수를 선언하고 초기화를 하지 않음.

그래서 ptr에는 쓰레기 값이 들어가고 거기에 200이라는 정수 값을

넣음. 이렇게 되면 ptr이 가리키는 주소가 어딘지 몰라 예기치못한

오류가 발생할 수 있음.

 

아래도 마찬가지로 125라는 정수 값을 넣어지만 가리키는 주소가

어딘지 몰라서 예기치못한 오류가 발생할 수 있음.


포인터 변수 예제

// 포인터 미사용
int Mul(int n)
{
	return 10 * n;
}

void main(void)
{
	int n;
	int m;

	printf("숫자 1개 입력: ");
	scanf("%d", &n);

	m = Mul(n);

	printf("\n%d의 10배 큰 수는 %d\n", n, m);
}

위는 포인터를 사용하지 않았음.

아래는 포인터를 사용함.

// 포인터 사용
void Mul(int n, int *k)
{
	*k = 10 * n;
}

void main(void)
{
	int n;
	int m;

	printf("숫자 1개 입력: ");
	scanf("%d", &n);

	Mul(n, &m);

	printf("\n%d의 10배 큰 수는 %d\n", n, m);
}

Mul(n, &m);에서 m에 &을 붙여서 실제 주소를 준다.

n으로는 값을 준다.

 

n이 준 값은 int형으로 받는다.

&m이 준 숫자가 있는 주소는 int *k로 받는다.

그렇게 되면 k에 m이 준 주소가 들어간다.

 

정리하면 n에는 입력받은 정수가 들어가고, m은 정수가 있는 숫자가 들어가고,

k는 m한테 받은 주소가 들어간다.

 

*k = 10 * n;에서

n에 들어간 정수에 10을 곱하고 그 값을

k에 있는 m의 주소 값에 값을 넣는다.

 

나중에 출력시 m의 주소 값에 값이 있기 때문에 그 값을 바로 출력한다.


숫자 교환하는 예제이다.

함수안에서의 지역변수끼리만 교환이 일어나므로

숫자는 바뀌지 않는다.

 

출력을 숫자를 바꾼 함수내에서 하면 정상적으로 바뀐다.

 

하지만 출력을 밖에서 하고싶으면 포인터를 사용하면 된다.

아래는 포인터 예제이다.

NumSwap(&n, &m)에서 n, m의 주소를 그대로 NumSwap의 *n과 *m에 보낸다.

NumSwap함수에서는 *n의 주소에 있던 n에서 입력받은 값을 tmp에 저장한다.

*m의 주소에 있던 값을 꺼내와서 *n의 주소에 넣는다.

그리고 tmp에 있던 정수를 *m의 주소에 넣는다.

 

이렇게 포인터로 주소를 주고받고 값을 바꾸는 것을

call by reference라고 한다.(주소 참조)

 

앞전에 했던 숫자를 복사했던 것은

call by value라고 한다.

 

두 개중에서 더 효율적인 것을 골라서 코딩을 하면된다.