ch12 포인터의 이해

암영·2022년 5월 16일
0

c언어

목록 보기
13/21

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

주소 값의 저장을 목적으로 선언되는 포인터 변수

다음과 같은 변수가 선언되었다고 가정해보자.

int main()

{
	char ch1='A',ch2='Q';
    int num=7;
    ...
}

그럼 총 6바이트 (1바이트+1바이트+4바이트)가 메모리 공간에 다음과 같이 할당된다.

위 그림에서 메모리 블록의 상단에 표시한것은 메모리 주소값 이다.그림에서 보이듯이 1바이트의 메모리 공간을 단위로 하나의 주소 값이 할당되며 주소값도 1씩 증가한다.

  • 포인터 변수를 잘 이해하기 위해서는 메모리 공간을 그림으로 그려가면서 공부해보기.

위의 그림을 보고 다음 질문에 답을 해보자.

Q int형 변수 num은 어디에 할당되어 있나요?
A int형 변수 num은 ox12ff76번지에서 ox12ff79번지에 걸쳐서 할당되어있다.
하지만 c언어 에서는 시작번지만 가지고 위치를 표현한다.
따라서 이렇게 답해도 된다.
int형 변수 num은 ox12ff76번지에 할당되어있다.

그런데 위의 대답에 포함되어 있는 주소값 역시 정수이다. 따라서 이것도 저장이 가능한 값이며, 이의 저장을 위해 마련된 변수가 바로 포인터 변수이다.

포인터 변수:메모리의 주소값을 저장하기 위한 변수
+) 변수형태의 포인터와 상수형태의 포인터를 어우르는 표현.

포인터 변수 & 연산자

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

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

포인터 변수의 선언: intpnum;
pnum :포인터 변수의 이름
int
:int형 변수의 주소값을 저장하는 포인터 변수의 선언

pnum= #

&연산자: 오르쪽에 등장하는 피연산자의 주소값을 반환하는 연산자.

포인터 변수 pnum이 int형 변수 num을 가리킨다.

포인터변수 선언하기

변수의 자료형==포인터 변수의 자료형!

int pnum1;
int
는 int형 변수를 가리키는 pnum1의 선언을 의미함
doublepnum2;
double
는 double형 변수를 가리키는 pnum2의 선언을 의미함.

포인터의 형

포인터 형: 포인터 변수의 선언 및 구분에 사용되는 int,char등을 가리킨다.

ex) int* :int형 포인터

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

변수의 주소값을 반환하는 연산자

&연산자: 피연산자의 주소값을 반환함.

int main()
{
	int num=5;
    int *pnum=#//num의 주소값을 반환해서 포인터 변수 pnum을 초기화
}
  • &연산자의 피연산자는 변수여야하며,상수는 피연산자가 될수 없다.
  • 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될수 있다.
int main()
{
 	int num1=5;
    double*pnum1=&num1;//일치하지 않음!
    
    double num2=5;
    int*pnum2=&num2;//일치하지 않음
}

포인터가 가리키는 메모리를 참조하는 * 연산자

    • 연산자:포인터가 가리키는 메모리 공간에 접근할때 사용하는 연산자
int main()
{
	int num=10;
    int*pnum=#//포인터 변수 pnum이 변수 pnum을 가리키게 하는 문장
    *pnum=20;//pnum이 가리키는 변수에 20을 저장하라!
    printf("%d",*pnum);//pnum이 가리키는 변수를 부호 있는 정수로 출력하라!
}

*pnum=20; :포인터 변수 pnum이 가리키는 메모리 공간인 변수 num에 정수 20을 저장해라!
printf("%d",*pnum); :포인터변수 pnum이 가리키는 메모리 공간인 변수 num에 저장된 값을 출력해라!

#include <stdio.h>
int main()
{
	int num1 = 100, num2 = 100;
	int* pnum;

	pnum = &num1; //포인터 pnum이 num1을 가리킴
	(*pnum) += 30;
	pnum = &num2;//포인터 pnum이 num2를 가리킴
	(*pnum) -= 30;//num2-=30;과 동일

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

위예제의 흐름정리

다양한 '포인터 형'이 존재하는 이유

(*) 연산자를 통한 메모리 공간의 접근 기준을 마련하기 위함이다.(메모리공간을 참조하는 기준이 됨)
ex)pnum이 int형 포인터 변수라고 가장하면, pnum이 int형 포인트 변수이므로 pnum에 저장된 주소를 시작으로 4바이트를 읽어들여 이를 정수로 해석해야 합니다.

문제 12-1:포인터의 이해

문제1

문제2
int형 변수num1과 num2를 선언과 동시에 각각 10과 20으로 초기화하고, int현 포인터 변수 ptr1,ptr2를 선언하여 각각 num1과 num2를 가리키게 하자. 그리고 이 상태에서 포인터 변수 ptr1과 ptr2를 이용해서 num1의 값을 10증가시키고,num2의 값을 10 감소시키자.
이제 두 포인터 변수 ptr1과 ptr2가 가리키는 대상을 서로 바꾸자. 즉, 포인터 변수 ptr1이 num2를 가리키게 하고, 포인터변수 ptr2가 num1을 가리키게 하자. 그리고 마지막 ptr1과 ptr2가 가리키는 변수에 저장된 값을 출력하자.

#include <stdio.h>
int main()
{
	int num1 = 10, num2 = 20;
	int* ptr1 = &num1;
	int* ptr2 = &num2;
	(*ptr1) += 10;
	(*ptr2) -= 10;
	int* temp;
	temp = ptr1;
	ptr1 = ptr2;
	ptr2 = temp;
	printf("%d %d", *ptr1,*ptr2);
	

	return 0;
}

잘못된 포인터 사용과 널 포인터

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

잘못된 예)

int main()
{
	int *ptr;//포인터 변수 ptr은 쓰레기 값으로 초기화됨.
    *ptr=200;
}

어디를 가리킬지 모르는 상태에서 (*)연산을 통해 200을 저장하는 것은 치명적인 결과로 이어질 수 있다.

잘못된예2)

int main()
{
	int*ptr=125; //125번지가 어딘 줄 알고?
    *ptr=10;
}
  • 포인터 변수를 선언하는 방법
    포인터 변수를 선언만 해두고, 이후에 유호한 주소값을 채워 넣을 생각이라면 다음과 같이 초기화를 하는게 좋다.
int main()
{
	int*ptr1=0;
    int*ptr2=NULL;//NULL은 사실상 0을 의미한다.
}

ptr1을 초기화하는 값 0을 가리켜 널포인터라 한다.
:아무데도 가리키지 않는다는 뜻.

profile
just do! -얼레벌레 굴러가는 공대생

0개의 댓글