2022. 11. 21. 21:38ㆍC언어/기본 개념
메모리의 주소
이때까지 우리가 저장해 왔던 데이터는 메모리의 위치를 주소 값으로 식별할 수 있다.
주소 값은 바이트 단위로 구분 되고 0부터 1씩 증가한다.
예를 들어 int형 a가 메모리 100번지부터 할당 되었다면 a는 100 ~ 103번지까지 4바이트로 할당 될 것이다.
주소연산자 : &
#include <stdio.h>
int main(void)
{
int a;
double b;
char c;
printf("int형 변수의 주소 : %u\n", &a);
printf("double형 변수의 주소 : %u\n", &b);
printf("char형 변수의 주소 : %u\n", &c);
return 0;
}
int형 변수의 주소 : 447740868 double형 변수의 주소 : 447740904 char형 변수의 주소 : 447740932 |
변수 a는 447740868번지부터 447740871번지까지 4바이트를 사용했다.
변수 b는 447740904번지부터 447740911번지까지 8바이트를 사용했다.
변수 c는 447740932번지부터 447740932번지까지 1바이트를 사용했다.
▶보통 주소는 16진수로 표기한다. 따라서 출력 할 때 %p를 사용하는 것이 좋다.
위에서 %u를 사용한 이유는 편의상 10진수로 출력하고 주소는 음수가 없으므로 %u를 사용했다.
포인터와 간접 참조 연산자 : *
이번에는 할당된 메모리 주소를 활용하는 방법을 살펴보겠다.
한 번 구한 주소를 저장해서 사용해야 편리한데, 포인터가 바로 변수의 메모리 주소를 저장하는 변수이다.
선언 할 때 변수 앞에 *만 사용해주면 된다
#include <stdio.h>
int main(void)
{
int a;
int* pa;
pa = &a;
*pa = 10;
printf("포인터로 a 값 출력 : %d\n", *pa);
printf("변수명으로 a값 출력 : %d", a);
return 0;
}
pa = &a; 는 pa변수에 a의 주소를 저장하는 것이다.
*pa = 10; 은 현재 주소의 들어있는 값을 10으로 저장한다는 뜻이다. (a의 값을 바꿔버린다는 것)
#include <stdio.h>
int main(void)
{
int a = 10, b = 15, total;
double avg;
int* pa, * pb;
int* pt = &total;
double* pg = &avg;
pa = &a;
pb = &b;
*pt = *pa + *pb;
*pg = *pt / 2.0;
printf("두 정수의 값 : %d, %d\n", *pa, *pb);
printf("두 정수의 합 : %d\n", *pt);
printf("두 정수의 평균 : %.1lf", *pg);
return 0;
}
pa와 pb는 a, b의 주소 값을 받는다.
*pt변수(변수 total의 주소)에 *pa(pa주소에 들어 있는 값 : 15) + *pb(pb주소에 들어있는 값 : 15) 값을 저장한다.
*pg변수(변수 avg의 주소)에 *pt를 2.0으로 나눈다.
const
const를 사용한 포인터는 가리키는 변수의 값을 바꿀 수 없다는 뜻이다.
#include <stdio.h>
int main(void)
{
int a = 10, b = 20;
const int* pa = &a;
printf("a 값 : %d\n", *pa);
pa = &b;
printf("b 값 : %d\n", *pa);
pa = &a;
a = 20;
printf("a 값 : %d", *pa);
return 0;
}
a 값 : 10 b 값 : 20 a 값 : 20 |
const를 사용했음에도 불구하고 pa = &b;를 선언한 후에 출력한 b 값은 정상적으로 출력된다. 그렇다면 const를 선언해서 달라진게 무엇이냐면, pa가 가리키는 변수 a는 pa를 간접 참조하여 바꿀 수 없다는 의미다.(*pa =20; 과 같이 할 수 없음)
주소와 포인터의 차이
주소 : 변수에 할당된 메모리 저장 공간의 시작 주소 값 그 자체
포인터 : 그 값을 저장하는 또 다른 메모리 공간
'다른 메모리 공간' 이 말은 즉 두 포인터가 같은 주소를 저장하는 것이 가능하다.(동시에 가리키는 일)
int a; int *pa, *pb; pa = pb = &a; |
포인터 대입 규칙
- 포인터는 가리키는 변수의 형태가 같을 때만 대입해야 한다.(int는 int에만 double은 double에만)
- 형 변환을 사용한 포인터의 대입은 가능하다.(pi = 100; 처럼 사용하면 주소 값이 아닌 정수이기 때문에 안 된다.)
double a= 3.4; double *pd = &a; int *pi; pi = (int *)pd; |
포인터를 사용하는 이유
포인터를 사용하려면 추가적으로 변수를 선언 해줘야한다. 주소연산, 간접 참조 연산 등 다양한 연산을 수행야한다. 그래서 굳이 사용할 필요는 없다. 하지만 임베디드 프로그래밍을 할 때 메모리에 직접 접근 하는 경우나 동적 할당한 메모리를 사용하는 경우에는 반드시 필요합니다.
결론
주소와 포인터는 상수와 변수의 차이가 있다.
포인터의 크기는 주소의 크기와 같다.(자료형)
'C언어 > 기본 개념' 카테고리의 다른 글
[C] 문자 (0) | 2022.11.25 |
---|---|
[C] 배열과 포인터 (0) | 2022.11.24 |
[C] 배열 - Kyeom (0) | 2022.11.18 |
[C] 함수-Kyeom (0) | 2022.11.17 |
[C] 반복문(break, continue) - Kyeom (0) | 2022.11.17 |