Chap.12 포인터의 이해

xyzw·2022년 9월 5일
0

C

목록 보기
1/6

12-1; 포인터란 무엇인가?

포인터 변수 선언하기

포인터 변수는 가리키고자 하는 변수의 자료형에 따라서 선언하는 방법이 달라진다.

type* ptr;  //type형 변수의 주소 값을 저장하는 포인터 변수 ptr의 선언

포인터 변수의 선언 및 구분에 사용되는 int* 등을 가리켜 '포인터 형'이라 한다. 포인터의 형은 메모리 공간을 참조하는 기준이 된다.

예시

정수 7이 저장된 int형 변수 num을 선언하고(1) 이 변수의 주소 값 저장을 위한 포인터 변수 pnum을 선언하자.(2) 그리고 나서 pnum에 변수 num의 주소 값을 저장하자.(3)

int main(void) {
	int num = 7; //(1)
	int* pnum;   //(2)
	pnum = # //(3) 
    ...
}

변수 num의 주소 값이 0x12ff76 ~ 0x1279 라고 한다면, 포인터 변수 pnum에는 변수 num의 시작번지 주소 값인 0x12ff76이 저장된다. 즉, num에는 7이 저장되어있고, pnum에는 0x12ff76이 저장되어있다.
(포인터 변수의 크기는 주소 값의 크기와 동일하다.)

12-2; 포인터와 관련 있는 연산자: & 연산자와 * 연산자

& 연산자

피연산자의 주소 값을 반환한다. 이때 피연산자는 상수가 아닌 변수이어야 하고, 변수의 자료형과 포인터형이 일치해야 한다.

* 연산자

포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.

int main(void)
{
	int num = 10;
    int* pnum = #     // 포인터 변수 pnum이 변수 num을 가리키게 함
    *pnum = 20;           // pnum이 가리키는 변수에 20을 저장
    printf("%d", *pnum);  // pnum이 가리키는 변수를 부호 있는 정수로 출력
    ...
}

여기서 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.

예시

#include <stdio.h>

int main(void)
{
	int num1 = 100, num2 = 100;
    int* pnum;
    
    pnum = &num1;  // 포인터 pnum이 num1을 가리킴
    (*pnum) += 30; // num1 += 30; 과 동일
    
    pnum = &num2;  // 포인터 pnum이 num2를 가리킴
    (*pnum) -= 30; // num2 -= 30; 과 동일
    
    printf("num1:%d, num2:%d \n", num1, num2);
    return 0;
}

실행 결과
num1:130, num2:70

참고

일반 변수와 포인터 변수를 하나의 문장 안에서 동시에 선언하는 것도 가능하다.

int num, *pnum;

그러나 선언하고자 하는 변수의 형이 다르면 문장을 달리해서 선언하는 것이 좋다.

// 더 좋은 코드
int num;
int * pnum;

포인터 변수 초기화

포인터 변수는 초기화를 꼭 하기

포인터 변수를 선언만 하고 초기화하지 않으면, 포인터 변수는 쓰레기 값으로 초기화된다.

포인터 변수는 상수로 초기화하지 않기

int main(void)
{
	int* ptr = 125;
    *ptr = 10;
}

위와 같이 포인터 변수를 일반 상수로 초기화하는 것은 쓰레기 값으로 초기화한 것과 다르지 않다.
포인터 변수를 우선 선언만 해놓고, 이후에 유효한 주소 값을 채워 넣을 것이라면 다음과 같이 초기화하는 것이 좋다.

int main(void)
{
	int* ptr1 = 0;
	int* ptr2 = NULL;  //NULL은 사실상 0을 의미함
}

이때 ptr1을 초기화하는 값 0은 '널 포인터'라고 한다. 이는 "아무데도 가리키지 않는다"는 의미이다.

문제

1.

Q. 아래의 예제 실행 시 변수와 포인터 변수의 관계를 그림을 그려서 설명해보자. 또한 출력의 결과도 예상해보자.

int main(void)
{
	int num = 10;
    int* ptr1 = &num;
    int* ptr2 = ptr1;
    
    (*ptr1)++;
    (*ptr2)++;
    printf("%d \n", num);
    return 0;
}

A.

변수와 포인터 변수의 관계

출력의 결과: 12

2.

Q. int형 변수 num1 과 num2를 선언과 동시에 각각 10과 20으로 초기화하고, int형 포인터 변수 ptr1 과 ptr2를 선언하여 각각 num1 과 num2를 가리키게 하자. 그리고 이 상태에서 포인터 변수 ptr1 과 ptr2를 이용해서 num1 의 값을 10 증가시키고, num2의 값을 10 감소시키자.

이제 두 포인터 변수 ptr1 과 ptr2가 가리키는 대상을 서로 바꾸자. 즉, 포인터 변수 ptr1이 num2를 가리키게 하고, 포인터 변수 ptr2가 num1을 가리키게 하자. 그리고 마지막으로 ptr1과 ptr2가 가리키는 변수에 저장된 값을 출력하자.

A.

#include <stdio.h>

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

주의할 점

ptr1과 ptr2가 가리키는 대상을 바꿀 때, 포인터 변수에 *를 붙이지 않도록 주의하자.
만약 아래와 같이 코드를 작성한다면, 실행 결과는 (num2의 주소 값), (num1의 주소 값)이 될 것이다.

*ptr1 = &num2;  //num1 = &num2과 동일
*ptr2 = &num1;  //num2 = &num1과 동일

0개의 댓글