[C] 포인터 배열 ver.

장세민·2022년 10월 16일
0

📝 TIL

목록 보기
26/40

📌 포인터 배열

📖 포인터 배열 선언과 사용

포인터는 주소를 저장하는 용도로 쓰이지만, 일반 변수처럼 메모리에 저장 공간을 갖는 변수이다.
따라서 같은 포인터가 많이 필요한 경우 배열을 만들어 사용하면 편할 것이다.

포인터 배열은 같은 자료형의 포인터를 모아 만든 배열이다.

포인터 배열로 여러 개의 문자열을 출력해보자.

  1. #include <stdio.h>
  2.  
  3. int main(void)
  4. {
  5. char *pary[5];
  6. int i;
  7.  
  8. pary[0] = "dog";
  9. pary[1] = "elephant";
  10. pary[2] = "horse";
  11. pary[3] = "tiger";
  12. pary[4] = "lion";
  13.  
  14. for (i = 0; i < 5; i++)
  15. {
  16. printf("%s\n", pary[i]);
  17. }
  18.  
  19. return 0;
  20. }
  21.  

포인터 배열의 선언 방식은 배열 요소의 자료형이 포인터형이므로
배열명 앞에 별(*)을 붙인다.

결국 5행은 char *형 변수 5개를 요소로 갖는 포인터 배열의 선언이다.

8~12행까지는 포인터 배열의 각 요소에 문자열 상수를 대입한다.
문자열 상수는 변경이 불가능한 메모리 영역에 보관되고,
포인터 배열에는 그 첫 번째 문자의 주소가 저장된다.

그림으로 이해해보자.

포인터 배열의 각 요소는 문자열 상수가 저장된 메모리의 주소를 가지므로
변환 문자 %s로 출력하면 각 요소가 연결하고 있는 문자열을 출력한다.


🚨 중요

포인터 배열은 다른 배열처럼 메모리에 연속해서 위치하지만,
각 요소에 저장된 주소 값은 개별적인 문자열들의 주소이므로 연속성 x


포인터 배열의 초기화

char 포인터 배열의 초기화는 2차원 char 배열의 초기화와 같다.

char 포인터 배열의 초기화

char *pary[5] = {"dog", "elephant", "horse", "tiger", "lion"};

2차원 char 배열의 초기화

char animal[5][20] = {"dog", "elephant", "horse", "tiger", "lion"};

포인터 배열은 문자열의 시작 주소를 배열 요소에 저장하고,
2차원 char 배열은 문자열 자체를 배열 공간에 저장한다.



📖 2차원 배열처럼 활용하는 포인터 배열

포인터 배열은 첨자를 하나 사용하는 1차원 배열이지만,
1차원 배열을 포인터 배열로 연결하면 2차원 배열로 활용할 수 있다.

한 번 해보자.

  1. #include <stdio.h>
  2.  
  3. int main(void)
  4. {
  5. int ary1[4] = {1, 2, 3, 4};
  6. int ary2[4] = {11, 12, 13, 14};
  7. int ary3[4] = {21, 22, 23, 24};
  8. int *pary[3] = { ary1, ary2, ary3 };
  9.  
  10. int i, j;
  11.  
  12. for (i = 0; i < 3; i++)
  13. {
  14. for (j = 0; j < 4; j++)
  15. {
  16. printf("%5d", pary[i][j]);
  17. }
  18. printf("\n");
  19. }
  20.  
  21. return 0;
  22. }
  23.  

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차원 배열과 달리 각 행의 배열끼리는 메모리에 연속으로 할당되지 않기 때문이다.


포인터 배열이 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)
profile
분석하는 남자 💻

0개의 댓글