C언어) 포인터의 이해

반응형

C언어) 논리 연산

포인터란

 

포인터는 C언어에서 다른 변수의 주소를 저장하는 특별한 변수다.

포인터에 저장되는 변수의 주솟값을 이용하면 프로그램을 보다 간결하고 효율적으로 다룰 수 있다.

 

 

주소(adress)와 포인터

 

변수를 선언하면 해당 변수에 메모리가 할당된다.

주소는 이 메모리의 저장 장소의 위치를 나타낸다.

이 주소를 통해 변수의 값을 다루면, 보다 융통성있는 프로그램을 만들 수 있다.

이때 주소를 저장하기 위한 변수가 포인터다.

 

 

포인터 선언

 

포인터는 그 포인터가 가리키는 변수의 자료형과 같은 자료형으로 선언해야 한다.

이때 자료형과 포인터의 이름 사이에 *을 적어준다.

*은 선언하는 변수가 포인터임을 나타낸다.

 

자료형* 포인터명;

 

*의 위치는 자료형과 포인터의 이름 사이에만 위치하면 된다.

 

int* ptr;

int *ptr;

 

여러 개의 포인터를 동시에 선언할 때는 포인터의 이름마다 *을 붙여주면 된다.

 

int *ptr1, *ptr2, *ptr3;

 

만약 다음과 같이 선언하면 ptr1만 포인터로 선언되고 ptr2ptr3는 일반적인 정수형 변수로 선언된다.

 

주의) int* ptr1, ptr2, ptr3;

 

포인터는 메모리의 주소를 직접 다루는 변수기 때문에 꼭 초기화를 해줘야 한다.

이때 변수의 주소를 얻기 위해 주소 연산자(&)를 사용한다.

반대로 포인터에 저장된 주소의 변수를 다룰 때는 역참조 연산자(*)를 사용한다.

포인터의 이름 앞에 *을 적어주면 해당 주소에 저장된 변수의 값을 반환하게 된다.

 

자료형* 포인터명 = &변수명(주소);
자료형* 포인터명;
포인터명 = &변수명(주소);

 

스타터를 위한 팁

이 두 연산자의 역할을 정확히 알지 못하고 혼동되면 이후에 포인터를 활용할 때 엄청난 어려움을 겪는다.
정확한 개념은 아니지만 간단하게 다음 한 문장으로 기억해두면 큰 도움이 될 것이다.
변수에 &를 붙이면 주소가 되고, 주소에 *을 붙이면 변수가 된다.”

 

<예제 코드>

#include<stdio.h>

int main()
{
	int number = 10;
	int* ptr = &number;
	
	//%p는 주소를 출력하는 서식 문자이다
	printf("number의 주소 : %p \n", &number); 
	// (출력 예시) number의 주소 :  000000AEF40FFCB4
	printf("p에 저장된 주소 : %p \n", ptr);
	// (출력 예시) p가 가리키는 주소 :  000000AEF40FFCB4
	printf("p에 저장된 주소에 있는 변수에 저장된 값 : %d \n", *ptr);
	// (출력) p가 가리키는 주소에 저장된 값 : 10

	return 0;
}

 

예제코드드에서 먼저 정수형 변수 number를 선언해주고 포인터 ptrnumber의 주소를 저장했다.

이후 서식 문자 %p를 이용하여 주소를 16진수로 출력해보면 &number 의 출력 결과와 ptr 의 출력 결과가 같은 걸 확인할 수 있다.

그리고 *ptr의 값은 number에 저장된 값인 10이 출력된다.

 

변수의 주소

포인터는 컴퓨터마다, 컴파일할 때마다 다른 값이 출력된다. 변수의 주소를 출력해보면 같은 코드인데도 예제와 다른 결과가 나올 것이다.

 

<예제코드>

#include<stdio.h>

int main()
{
	int number = 10;
	int CopyNumber = number; // number의 값을 저장
	int* ptr = &number; // number의 주소를 저장

	printf("CopyNumber = %d \n", CopyNumber);
	// (출력) CopyNumber = 10
	printf("*ptr = %d \n", *ptr);
	// (출력) CopyNumber = 10

	number = 20; //number의 값을 20으로 변경
	
	printf("CopyNumber = %d \n", CopyNumber);
	// (출력) CopyNumber = 10
	printf("*ptr = %d \n", *ptr);
	// (출력) CopyNumber = 20

	return 0;
}

 

CopyNumberptr의 선언 시점에 각각 number의 값과 number의 주소를 저장하고 CopyNumber를 출력하면 10, *ptr을 출력하면 10이 나온다.

그런데, number의 값을 20으로 바꾸고 다시 출력하면 CopyNumber는 똑같이 10이 출력되지만 *ptr20이 출력된다.

CopyNumber에 변경된 number의 값을 다시 대입한 적은 없기 때문에 10이 출력되는 것은 당연하다.

하지만 ptrnumber의 주소를 가리키고 있기 때문에 다시 number의 값을 대입하지 않아도 number의 변경된 값을 출력하는 것이다.

 

만약 포인터에 저장된 주소를 비우거나 아무런 주소도 가리키지 않게 하려면 ‘NULL’을 사용한다.

포인터명 = NULL;

 

<예제코드>

#include<stdio.h>

int main()
{
	int number = 10;
	int* p = &number;

	printf("number의 주소 : %p \n", &number);
	// (출력) number의 주소 :  000000AEF40FFCB4
	printf("p에 저장된 주소 : %p \n", p);
	// (출력) p가 가리키는 주소 :  000000AEF40FFCB4

	p = NULL; //포인터가 아무런 주소도 가리키지 않게 한다
	
	printf("p에 저장된 주소 : %p \n", p);
	// (출력) p에 저장된 주소 : 0000000000000000

	return 0;
}

 

반응형

'C language' 카테고리의 다른 글

C언어) 함수 사용  (0) 2023.06.24
C언어) 함수에 대하여 & 함수 정의 방법  (0) 2023.06.23
C언어) 논리 연산  (0) 2023.06.07
C언어) 관계 연산자  (0) 2023.06.06
C언어) [조건문] switch문  (0) 2023.06.06