포인터는 주소를 저장하는 용도로 쓰이지만, 일반 변수처럼 메모리에 저장 공간을 갖는 변수이다.
따라서 같은 포인터가 많이 필요한 경우 배열
을 만들어 사용하면 편할 것이다.
포인터 배열은 같은 자료형
의 포인터를 모아 만든 배열이다.
#include <stdio.h> int main(void) { char *pary[5]; int i; pary[0] = "dog"; pary[1] = "elephant"; pary[2] = "horse"; pary[3] = "tiger"; pary[4] = "lion"; for (i = 0; i < 5; i++) { printf("%s\n", pary[i]); } return 0; }
포인터 배열의 선언 방식은 배열 요소의 자료형이 포인터형이므로
배열명 앞에 별(*)
을 붙인다.
결국 5행은 char *형 변수 5개를 요소로 갖는 포인터 배열의 선언이다.
8~12행까지는 포인터 배열의 각 요소에 문자열 상수를 대입한다.
문자열 상수는 변경이 불가능한 메모리 영역에 보관되고,
포인터 배열에는 그 첫 번째 문자의 주소
가 저장된다.
포인터 배열의 각 요소는 문자열 상수가 저장된 메모리의 주소
를 가지므로
변환 문자 %s로 출력하면 각 요소가 연결하고 있는 문자열을 출력한다.
포인터 배열
은 다른 배열처럼 메모리에 연속해서 위치하지만,
각 요소에 저장된 주소 값
은 개별적인 문자열들의 주소이므로 연속성 x
char 포인터 배열의 초기화는 2차원 char 배열의 초기화와 같다.
char *pary[5] = {"dog", "elephant", "horse", "tiger", "lion"};
char animal[5][20] = {"dog", "elephant", "horse", "tiger", "lion"};
포인터 배열은 문자열의 시작 주소
를 배열 요소
에 저장하고,
2차원 char 배열은 문자열 자체
를 배열 공간
에 저장한다.
포인터 배열은 첨자를 하나 사용하는 1차원 배열이지만,
1차원 배열을 포인터 배열로 연결하면 2차원 배열로 활용할 수 있다.
#include <stdio.h> int main(void) { int ary1[4] = {1, 2, 3, 4}; int ary2[4] = {11, 12, 13, 14}; int ary3[4] = {21, 22, 23, 24}; int *pary[3] = { ary1, ary2, ary3 }; int i, j; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%5d", pary[i][j]); } printf("\n"); } return 0; }
5~7행의 int형 배열들의 배열명은 첫 번째 요소의 주소이므로 포인터에 저장할 수 있다.
만약 ary3 배열의 두 번째 저장 공간에 있는 22를 출력하고 싶다면
printf("%5d", pary[2][1]);
다음과 같이 코드를 작성하여 컴파일을 진행하면 된다.
포인터 배열 pary는 배열명
처럼 사용되고,
각 배열 요소 pary[0], pary[1], pary[2]는 부분배열명
의 기능을 한다.
예를 들어 세 번째 배열만 5개 요소가 있는 경우로 고쳐보면
int ary3[5] = {21, 22, 23, 24, 25};
첫 번째 배열의 다섯 번째 요소와 두 번째 배열의 다섯 번째 요소는 쓰레기 값이 출력된다.
이번에는 두 번째 배열을 요소가 5개인 배열로 수정해보면
마찬가지로 나머지 배열 요소는 쓰레기 값이지만,
두 번째 배열의 다섯 번째 요소는 0이 출력된다.
이는 2차원 배열과 달리 각 행의 배열끼리는 메모리에 연속으로 할당되지 않기 때문이다.
바로 포인터 연산 때문이다.
포인터는 자신이 가리키는 변수의 형태를 알고 있으므로
정수 연산을 통해 원하는 위치를 찾아갈 수 있는 것이다.
pary[2][1]의 배열 표현식으로 어떻게 22의 값을 사용하려면
먼저, 포인터 표현으로 바꿔준다.
*(pary[2] + 2);
pary[2]는 int형 변수를 가리키는 포인터이므로
그곳에 저장된 300은 int형 변수의 주소이다.
따라서 이 값에 1를 더하면 int형의 크기인 4를 곱해서 더하므로 304가 된다.
이 값은 ary3 배열의 두 번째 요소의 주소가 된다!
*(pary[2] + 2) → *(300 + (2 * sizeof(int))) → *(300)