C언어의 포인터

Devkty·2025년 4월 13일
0

C언어 포인터

포인터는 메모리의 주소값을 저장하는 변수입니다.

포인터를 왜 써야할까?

  • 함수에서의 값 전달(call by reference)
  • 동적 메모리 할당(malloc, free)
  • 배열과 문자열 처리
  • 구조체와 연결 리스트 구현

포인터의 종류

포인터에서는 크게 두가지의 연산자가 있습니다.

  1. 참조 연산자인 * (주소에 저장된 값을 반환)
  2. 주소 연산자인 & (주소값을 반환)

예시를 들어 설명해보겠습니다.

int x = 10;     # x변수를 10으로 선언
int* p = &x;    # 포인터로 x주소 선언

위 식에서 *p는 포인터로 선언을 해줍니다.(하나의 변수)

&x는 변수 x가 저장되어있는 주소값을 의미합니다.

즉, 위의 수식은 x의 주소값을 &x를 통해 불러오고, p는 주소에 저장된 값을 반환하므로 해당 주소값에 있는 10을 가져옵니다. 그러면 p = 10을 출력하게 됩니다.

그럼 만약에 int *p = &x 라고 했을때 p의 값은 무엇일까요?
→ p는 &x이므로 x가 저장되어있는 주소값이 출력되게됩니다. 예를 들면, 0x10처럼 말입니다. 메모리 어딘가에 저장해뒀기 때문에 상황에 따라 다르게 나옵니다.

배열과 포인터, 포인터 연산

그럼 어떤 배열의 값을 포인터를 활용해서 알아봅시다.

int s[3] = {10, 20, 30};
s[0] = s;
s[1] = s+1;
s[2] = s+2;

위의 s, s+1, s+2이 주소라고 할 때, s, s+1, *s+2 로 값을 로드할 수 있습니다.

하나의 예시를 더 들어 보겠습니다.

int arr[3] = {1, 2, 3};
int *p = arr;
printf("%d\n", *(p+1)); // 2 출력
OR
p++;                    // 다음 요소
printf("%d\n", *p);     // 2

위의 식에서 *p에 배열을 선언해줬습니다. 배열이름은 사실상 첫 번째 요소의 주소를 의미합니다.

그러므로 arr == &arr[0]입니다. 그러므로 *(p+1)은 주소값 안에있는 저장된 값에 +1을 했음을 의미하므로 2번째 값인 2를 출력할 수 있습니다.

또 다른 방법은 p값에 +1을 하는 p++을 통해 다음 요소를 불러와 출력할 수 있습니다.

포인터와 함수

포인터를 통해 함수의 값을 바꿔보겠습니다.

void change(int *p) {
*p = 100;
}

int main() {
int a = 10;
change(&a);
printf("%d\n", a); // 100
}

main 함수에서 a는 10을 의미합니다. 그러나 바로 아래에 함수 change(&a) 가 있습니다.

change함수에 따르면 p는 100을 의미합니다.
근데 &a라는 주소값을 change 함수에 전달 했으니, int
p = &a이되고 *p = 100이니까 최종적으로 a값이 100으로 출력됩니다.

이중 포인터

포인터 변수는 메모리 주소를 갖는데, 이중포인터는 이러한 포인터의 변수도 메모리를 할당받는 변수이다.

즉, 다른 포인터 변수의 주소를 갖는 포인터를 말합니다.

int a = 10;
int *p = &a;
int **pp = &p;
printf("%d\n", **pp); // 10

위의 예시에서 a는 10입니다. *p는 &a로 10입니다. 그런데 이러한 메모리 주소값 p를 메모리에 할당해서 p의 주소값(&p)을 할당한 것이 이중포인터 **p입니다. 그래서 최종 결과도 10을 출력하게 됩니다.

profile
모든걸 기록하며 성장하고 싶은 개발자입니다. 현재 크래프톤 정글 8기를 수료하고 구직활동 중입니다.

0개의 댓글