Algorithm/C

[c언어 개념] #9 포인터의 포인터, 이중 포인터, 배열 포인터, 포인터 배열

하노정 2022. 7. 24. 20:19

c언어 개념 정리와 문제 풀이를 통해 알고리즘 수업을 준비하는 과정입니다. 그동안 수강했던 c언어 수업 자료와 윤성우의 열혈 C 프로그래밍의 내용을 포함해 저에게 기록할 가치가 있는 내용이 담겨 있습니다. 


포인터 변수를 가리키는 이중 포인터 변수(더블 포인터 변수)

포인터 변수는 종류에 관계없이 무조건 주소 값을 저장하는 변수이다. 

차이가 나는 것은 포인터 변수가 가리키는 대상일 뿐이다. 

 

이중 포인터 변수가 가리키는 대상은 싱글 포인터 변수이다. 

이중 포인터 변수에 들어가는 값은 싱글 포인터 변수의 주소 값이다. 

 

#include <stdio.h>

int main(void)
{
	double num = 3.14;
    	double *ptr = &num;
        double ** dptr = &ptr;
        double *ptr2;
        
        ptr2 = *dptr;
}

이중 포인터 사용에서 가리키는 대상이 헷갈릴 때가 있다.

그림을 연상하고 줄글로 이해하는 게 도움된다.

 

마지막 문장은 *dptr이 가리키는 곳을 ptr2도 가리키라는 뜻이다.

*dptr은 dptr이 가리키는 곳 = ptr이다.

ptr이 가리키는 곳을 ptr2도 가리키게 되므로 둘 다 num을 가리키게 된다. 

이중 포인터가 가리키는 곳, 싱글 포인터가 가리키는 곳단계적으로 떠올리면 된다. 

 

포인터의 필요성은?

함수 내에서 함수 외부에 선언된 변수에 접근하는 방법을 제시해 준다.

 

포인터 배열과 포인터 배열의 포인터 형

1차원 배열이름의 포인터 형을 결정짓는 것은 어렵지 않다.

배열이름이 가리키는 요소의 자료형만 고려하면 되기 때문이다.

 

그럼, int형 포인터 배열의 이름 arr1과 double형 포인터 배열의 이름 arr2의 포인터 형은?

arr1이 가리키는 첫 번째 요소는 int형 싱글 포인터이니, 배열이름 arr1은 int형 이중 포인터가 된다.

arr2가 가리키는 첫 번째 요소는 double형 싱글 포인터이니, 배열이름 arr2는 double형 이중 포인터가 된다. 

 

2차원 배열이름의 포인터 형

'포인터 형'은 포인터 대상의 증가 및 감소연산의 결과를 결정짓는 중요한 요소이다. 

2차원 배열이름을 대상으로 증가 및 감소연산을 할 경우, 연산결과는 각 행의 첫 번째 요소의 주소 값이 된다. 

arr1이 1행의 첫 번째 요소를 가리키면, arr+1이 반환하는 주소 값은 2행의 첫 번째 요소를 가리키게 된다.

 

따라서 2차원 배열을 이루는 요소의 자료형이 동일하더라도 배열의 가로길이가 다르면, 배열이름을 대상으로 하는 포인터 연산의 결과는 달라진다. 

 

2차원 배열이름의 포인터 형은 2차원 배열을 이루는 요소의 자료형이 동일하더라도 가로의 길이에 따라서도 달라진다.

이게 2차원 배열이름의 포인터 형 결정을 어렵게 하는 이유다.

 

2차원 배열이름의 포인터 형에는 다음 2가지 정보가 함께 담겨야 한다.

1. 가리키는 대상은 무엇인가?

2. 배열이름(포인터)을 대상으로 값을 1 증가 및 감소 시 실제로는 얼마가 증가 및 감소하는가?

 

int arr[3][4];

 

2차원 배열의 포인터 형은?

"arr은 가리키는 대상이 int형 변수이고, 포인터 연산 시 sizeof(int)x4의 크기단위로 값이 증가 및 감소하는 포인터 형이다."

 

그럼 포인터 변수 선언은?

int (*ptr) [4];

ptr이라는 이름의 포인터 변수를 선언한 것이며, 왼편에 선언된 int는 가리키는 대상의 자료형을 의미하며,

오른편에 있는 [4]는 한 번에 건너뛸 변수의 개수를 의미한다.

이러한 포인터 변수는 2차원 배열을 가리키는 용도로만 사용되기 때문에 이런 포인터 변수를 '배열 포인터 변수'라 한다.

 

'배열 포인터' vs '포인터 배열'

int (*ptr1) [4];   // 배열 포인터

int * ptr2 [4];    // 포인터 배열

 

외형적 차이는 소괄호의 유무인데 포인터 배열은 int * (ptr2 [4]); 와 같다. 포인터 배열의 요소들은 int형 포인터 변수이다.

 

ptr1은  포인터 변수 선언이고, ptr2는 배열 선언이다. 

 

ptr1는 가로길이가 4인 int형 2차원 배열을 가리키는 용도의 포인터 변수이고,

ptr2은 int형 포인터 변수로 이뤄진 int형 포인터 배열이다.

 

2차원 배열을 함수의 인자로 전달하기

다음 두 매개변수 선언은 동일한 선언이다. (매개변수 선언에서만 같은 의미다.)

int (*arr) [7];

int arr [][7];

 

2차원 배열에서도 arr[i]와 *(arr+i)는 같다.

arr[2][1] = 4;

(*(arr+2)) [1] = 4;