#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
'Embedded System > 소프트웨어 (C,C++)' 카테고리의 다른 글
[C/C++] Call By Value, Call by address (0) | 2023.08.07 |
---|---|
[Arduino] Wire 라이브러리 (0) | 2023.04.19 |
[C/C++] 이상형 월드컵 (ideal_worldCup) (0) | 2023.04.06 |
[Arduino] Servo 라이브러리 (0) | 2023.04.06 |
임베디드 C언어/ 툴체인 개념 (0) | 2023.01.31 |