[C] 포인터

2022. 11. 21. 21:38C언어/기본 개념

728x90

메모리의 주소

이때까지 우리가 저장해 왔던 데이터는 메모리의 위치를 주소 값으로 식별할 수 있다.

주소 값은 바이트 단위로 구분 되고 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;

포인터 대입 규칙

  1. 포인터는 가리키는 변수의 형태가 같을 때만 대입해야 한다.(int는 int에만 double은 double에만)
  2. 형 변환을 사용한 포인터의 대입은 가능하다.(pi = 100;  처럼 사용하면 주소 값이 아닌 정수이기 때문에 안 된다.)
double a= 3.4;
double *pd = &a;
int *pi;

pi = (int *)pd;

포인터를 사용하는 이유

포인터를 사용하려면 추가적으로 변수를 선언 해줘야한다.  주소연산, 간접 참조 연산 등 다양한 연산을 수행야한다. 그래서 굳이 사용할 필요는 없다. 하지만 임베디드 프로그래밍을 할 때 메모리에 직접 접근 하는 경우나 동적 할당한 메모리를 사용하는 경우에는 반드시 필요합니다.


결론

주소포인터는 상수와 변수의 차이가 있다.

포인터의 크기는 주소의 크기와 같다.(자료형)

728x90

'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