본문 바로가기
프로그래밍/C언어

8-3. 배열을 가리키는 포인터(배열포인터)

by 수삼이는코딩중 2023. 2. 16.
728x90

포인터

기억하기

arr[i]

는 컴파일러에 의해

*(arr+i)

로 변환된다. 

 

1차원 배열 가리키기

int* 포인터가 배열을 가리킬 수 있지 않을까? (배열의 원소가 int형일때!)

일단 이해 되지 않는 식을 써본다

#include <stdio.h>

int main() {
	int arr[3] = { 1,2,3 };
	int* parr;
	parr = arr;


	printf("arr[1] : %d \n", arr[1]);
	printf("parr[1] : %d \n", parr[1]);

	return 0;
}

결과는 다음과 같다

arr[1] : 2
parr[1] : 2

WHY?

parr[1] = *(parr+1)

따라서 arr의 첫번째 원소의 주소값을 가진 parr포인터로 arr 배열의 원소에 접근이 가능하다.

 

포인터의 포인터

int a=3;
int *p=&a;
int **pp=&p;

**pp는 int를 가리키는 p라는 포인터의 포인터이다. 

&과 *의 연산이 모두 성립된다. 간단하게 생각하면 된다!

하나만 예를 들면

*pp

는 무슨 값을 가질까?

pp라는 포인터가 가리키는 데이터의 값을 가리킨다. pp가 가리키는 데이터는 p이다. p에는 &a의 값이 들어있다.

따라서

printf("*pp의 값은? : %p\n",*pp)

결과는 다음과 같다.

*pp의 값은? : 0000002D09B4F4F4

 

배열을 가리키는 포인터!

1) int형 데이터를 가리키는 포인터 변수가 세개 들어있는 배열

int* parr[3]

2) int형 데이터를 3개 가지고 있는 배열arr을 가리키는 포인터

int(*parr)[3]=&arr

 

(arr은 암묵적으로 arr[0]의 주소값을 가리키는 포인터 변수로 변환이 되지만, sizeof와 &연산자랑 함께 쓰이변 변환되지 않는다. 그리고 반드시 (*parr)과 같이 괄호로 감싸줘야 한다.)

 

&arr은 무엇을 의미할까?

int arr[3]={1,2,3};
int (*parr)[3]=&arr;

여기서 &arr은 크기가 3인 배열arr의 주소값이 된다. 따라서  parr는 크기가 3인 배열을 가리키는 포인터가 되어야 한다. 그렇다면 *parr을 통해서 arr 배열의 원소를 참고하려면 어떻게 해야 하는가?

printf("parr[1] : %d \n", (*parr)[1])

위와 같이 접근할 수 있다.

 

#include <stdio.h>

int main() {
	int arr[3] = { 1,2,3 };
	int(*parr)[3] = &arr;

	printf("arr[1] : %d \n", arr[1]);
	printf("parr[1] : %d \n", (*parr)[1]);

	return 0;
}
arr[1] : 2
parr[1] : 2

따라서 arr[1]의 값은 (*parr)[1]과 같음을 알 수 있다. 

 

그러면 parr은 무슨 값을 가질까? 재밌게도 arr과 같은 값을 가진다. 

#include <stdio.h>

int main() {
	int arr[3] = { 1,2,3 };
	int(*parr)[3] = &arr;

	printf("arr : %p \n", arr);
	printf("parr : %p \n", parr);

	return 0;
}
arr : 00000015146FFCA8
parr : 00000015146FFCA8

arr과 parr 모두 첫번째 원소의 주소값을 출력한다. 물론 두개의 타입은 다르다. 

댓글