본문 바로가기
Embedded System/소프트웨어 (C,C++)

[C/C++] 포인터 개념 정리

by MachineJW 2022. 12. 21.
#include<stdio.h>

void pointer1();
void pointer2();
void pointer3();

void main()
{
	pointer1();
	pointer2();
	pointer3();
}

void pointer1()
{
	/*메모리의 주소는 필요할 때마다 계속 주소 연산을 수행하는 것보다 한번 구한 주소를 저장해서 사용하는것이 편리하다.*/
	/*포인터는 변수의 메모리 주소를 저장하는 변수 이다. 주소를 저장할 포인터도 변수처럼 선언하고 사용한다.*/
	
	int a;   // 일반변수 선언 
	int *pa; // 포인터 선언 
	// 포인터 선언 : 자료형 *변수명; 
	// 포인터 변수가 선언되면 일반 변수와 마찬가지로 메모리에 저장공간이 할당되고 그 이후에는 변수명으로 사용할수 있다. 
	// *는 간접 참조 연산자 또는 포인터 연산자라고 한다.  
	
	pa = &a; // 포인터에 a의 주소 대입, 주소연산자 & 
	// 만약 변수 a 가 메모리 100번지 부터 103번지 까지 할당되었다면 "시작 주소 값" 100이 pa에 저장된다. 
	// 이제 포인터 pa는 변수 a가 메모리 어디에 할당되었는지 그 위치를 기억하고있다.
	// 포인터 pa로 변수 a를 사용할 수 있다. 
	
	*pa = 10; //포인터 변수 a에 10 대입, 간접 참조 연산자 사용
	// 포인터 pa가 a를 가리키므로 *pa에 10을 대입하면 a에 10을 대입하는 것과 같다.  
	
	printf("pointer a 값 출력: %d",*pa);
	printf("\n변수 a 값 출력: %d",a); 
	
	if(*pa==a) // *pa와a는 같다. 
	{
	printf("\nint형 a변수의 주소: %p",&a); // %p는 주소값의 데이터의 크기에 따라 자릿수를 맞춰 16진수 대문자로 출력. 	
	}  
	
}

void pointer2()
{
	int a = 10, b = 15, total;
	double avg;
	
	/*포인터 선언*/
	int *pa = &a,*pb = &b; // 포인터 pa와 pb는 각각 int형 a와 b의 변수의 주소값을 담고 기억한다. 
	int *pt = &total; // 포인터 pt는 total이라는 int 형 변수의 주소값을 담는다. 
	double *pg = &avg; // 포인터 pg는 avg라는 double 형 변수의 주소값을 담는다. 
	
//	pa = &a; // pa포인터에 a의 주소 값을 대입 
//	pb = &b; // pb포인터에 b의 주소 값을 대입 
	
	*pt = *pa + *pb; //간접 참조 연산자를 사용하여 실제 변수 처럼 사용한다. 
	*pg = *pt / 2.0;
	
	
	printf("\n두 정수의 값 : %d,%d",*pa,*pb);
	printf("\n두 정수의 합: %d",*pt);
	printf("\n두 정수의 평균 : %.1lf",*pg);
	
	if(pa==&a&&pb==&b&&pt==&total&&pg==&avg)  
	{
	printf("\nint형 a변수의 주소: %p",pa);
	printf("\nint형 b변수의 주소: %p",pb);
	printf("\nint형 total변수의 주소: %p",pt);
	printf("\ndouble형 avg변수의 주소: %p",pg);        	
	}  
	
}

void pointer3()
{
	//const 예약어를 포인터에 사용하면 이는 가리키는 변수의 값을 바꿀 수 없다는 의미로 변수에 사용하는 것과는 다른 의미를 가진다.
	int a = 10, b = 20;
	const int *pa = &a; // 포인터를 상수화! 
	
	printf("\n변수 a 값 : %d",*pa); //포인터를 간접 참조하여 a 출력 
	pa = &b; // 포인터가 변수 b를 가리키게 한다. 
	printf("\n변수 b 값 : %d",*pa); // 포인터를 간접 참조하여 b 출력 
	pa = &a; // 다시 포인터pa가 변수 a를 가리키게 한다. 
	a = 20; // a를 "직접" 참조하여 값을 바꿈. *pa = 20;은 에러 메세지를 출력한다. 상수화된 포인터를 간접 참조하여 바꿀수 없기 때문. 
	printf("\n변수 a 값 : %d",*pa); // 포인터로 간접 참조하여 바뀐 값 출력.. 
	
	/*포인터에 사용된 const의 의미는 pa가 가리키는 변수 a는 pa를 "간접 참조"하여 바꿀 수 없다.*/
}
포인터를 표현하는 문장들...


능엄경(楞嚴經) 中..

너희들은 오히려 인연하는 마음으로 법을 듣고 있으니, 이 법도 인연일 뿐,
법의 본성을 얻은 것이 아니니라. 어떤 사람이 손으로 달을 가리켜 다른 사람에게 보인다면,
그 사람은 당연히 손가락을 따라 달을 보아야 하는데,
여기서 만일 손가락을 보고 달 자체로 여긴다면, 그 사람은 어찌 달만 잃었겠느냐.
손가락도 잃었느니라.

왜냐하면 가리킨 손가락을 밝은 달로 여겼기 때문이다. 어찌 손가락만 잃었다고 하겠느냐.
밝음과 어둠도 모른다고 하리라. 왜냐하면 손가락 자체를 달의 밝은 성질로 여겨서,
밝고 어두운 두 성질을 알지 못하기 때문이다.



포인터는 마녀이다. 하지만 포인터를 이해하면 마녀의 힘을 쓸 수 있다.

 

1. 메모리의 주소

포인터는 메모리의 주소 값을 저장하는 자료형이다.

메모리라는 것은 우리가 데이터를 넣고 꺼내 쓰는 공간이다.

메모리를 식별하는 주소값은 Byte 크기 (==8bit) 단위이다.

예를 들면 int형 변수 a(4Byte)가 메모리 100번지부터 할당되었다면 100번지~103번지까지 4바이트가 할당된다.

int a = 1; // int형 변수 선언
100 101 102 103
정수 1 (데이터)

 

2. 자료형의 메모리주소 값을 저장하는 자료형, 포인터

포인터는 위와 같이 선언된 자료형의 주소값을 저장하는 자료형이다.

포인터도 자료형이므로 언제든지 선언해줄수 있으며, * 기호를 사용하여 선언한다.

자료형의 주소값을 저장하는 자료형이기 때문에 포인터는 주소값을 저장해야한다.

int는 정수형, float이나 double은 실수형, char 문자형 처럼 int*,float*,double*,char* 과 같은 포인터는 주소값이 들어가야 한다.

해당 자료형의 주소값은 & (주소연산자)으로 구할 수 있다. 주소연산자는 해당 자료형의 메모리 시작 주소 값을 구한다.

주소연산자는 단항 연산자이며, 변수만을 피연산자로 사용하여 시작주소를 구한다.

int a = 1;
int* pa = &a; 
100 101 102 103
&a      
pa      
정수 1 (데이터)

이렇게 포인터로 선언이 되었을때, "pa는 a를 가리킨다", "pa -> a" 라고 표현한다.

pa는 주소값이지만 변수a 처럼 사용할 수 있다. 간접참조연산 *을 사용한다.

 

실습 참조

https://github.com/MachineJW/C/blob/main/0503_pointer2.c

 

GitHub - MachineJW/C: C언어/ 자료구조/ 알고리즘 훈련

C언어/ 자료구조/ 알고리즘 훈련. Contribute to MachineJW/C development by creating an account on GitHub.

github.com