• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

다중포인터의 메모리

21.03.21 15:37 작성 조회수 123

0

코드2 배열의 주소를 찍어봤을 때 4씩 늘어나는 것을 볼 수 있었습니다.

코드3 이중포인터를 사용한 배열의 주소를 찍어봤을 때 8이 늘어나는 것을 볼 수 있었습니다.

코드 4 행렬의 주소를 찍어봤을 때 열은 4씩 늘어나고 행은 20이 늘어난 것을 볼 수 있었습니다.

주소를 저장하는 공간은 정해져있는 것으로 알고 있는데 첫번째 코드의 경우 8이고, 두번째 코드의 경우 4이고 3번째 경우에는 8이며 네번째 코드의 경우는 다음 행과의 차이가 20인가요 잘못 비교를 하고 잇는 것같은데 뭐가 문제일까요

이중포인터 배열을 만들고 배열을 만들때의 메모리가 어떻게 할당이 되는지 궁금합니다. 그림을 그려서 이해해보려하는데 잘 안됩니다. 2차원 배열이라서 메모리 주소로 이해를 하면 안될 것 같은데 어떻게 생각하면 될까요?

cout << sizeof(int *) << endl; //8
-------------------------------------1
int *matrix = new int[3];
    
cout << matrix << endl; //0x...20
cout << &matrix[0] << endl; //0x...20
cout << &matrix[1] << endl; //0x...24
-------------------------------------2
int **matrix = new int *[3];
    
cout << matrix << endl; //0x...20
cout << &matrix[0] << endl; //0x...20
cout << &matrix[1] << endl; //0x...28
-------------------------------------3
int **matrix = new int*[3];
    
for(int r=0; r<3; r++)
matrix[r] = new int[3];
        
cout << &matrix[0][0] << endl; //0x..40
cout << &matrix[0][1] << endl; //0x..44
cout << &matrix[1][0] << endl; //0x..60
--------------------------------------4

답변 1

답변을 작성해보세요.

4

안소님의 프로필

안소

2021.03.21

https://www.inflearn.com/questions/134219

같은 강의의 질문인 위 링크에서 제가 이차원 배열의 그림을 첨부한적이 있습니다. 딱 아래 그림 생각하시면서 이해하시면 됩니다. (질문자님의 코드 같은 경우엔 열이 3 이 되겠네요 col = 3) 그냥 코드 1,2,3,4 차례차례 설명 드리겠습니다.

코드 1

64비트에서 실행하셨나보네요. 64비트 시스템에선 포인터(주소)의 크기는 8byte, 32비트 시스템에선 4byte 라는 것 이미 알고 계시겠지만 한번 짚고 넘어가겠습니다.

코드 2

matrix 는 int 형의 원소들을 가지는 배열이고 배열의 원소들은 메모리 내에서 따닥따닥 이웃사이로 붙어서 자리 잡고 있기 때문에 int 배열의 원소들끼리는 주소가 4 씩 차이나게 됩니다. int 는 4byte 크기의 데이터이기 때문입니다. 

코드 3

여기서부터 위 그림으로 이해하시는게 중요할 것 같네요.

int a[3] = {1, 2, 3} 여기서 a 는 배열의 이름이며 배열의 이름은 배열의 첫번째 원소의 주소를 나타낸다는 것을 알고 계실 것입니다. 배열은 같은 자료형의 원소들이 전부 딱붙어서 자리잡고 있으므로 사실 첫번째 원소의 주소만 알아도 두번째 원소, 세번째 원소 등등 그 이후의 원소들의 주소도 전부 산술 연산으로 알아낼 수 있습니다. (그래서 a[2] 은 곧 *(a + 2) 와 같죠.) 즉, 배열의 이름인 첫번째 원소의 주소로 그 배열 전체를 대표할 수 있습니다.

이차원 배열은 "1차원 배열들의 배열"이라고 생각하시면 됩니다. 즉 원소가 1차원 배열이라는 이야기인데, 배열이름은 곧 첫번째 원소의 주소를 뜻하죠. 그러니 int a[2][3] = { {1,2,3}, {4,5,6} } 에서 a[0] 은 { 1, 2, 3 } 배열, 즉 "{1, 2, 3} 배열의 첫번째 원소인 1 의 주소"라고 생각하시면 됩니다.  a[1] 은 { 4, 5, 6 } 배열의 첫번째원소인 4 의 주소가 되겠죠. a = { a[0], a[1] } 라고도 생각할 수 있습니다.

이중포인터도 똑같습니다. 

코드 3에서의 matrix 는 int* 타입의 원소들이 담긴 크기 3 배열의 주소를 가리키는 포인터입니다.(배열의 원소가 포인터이므로 첫번째 원소의 주소는 포인터의 포인터인 셈이니 이중포인터) 즉, matrix = { matrix[0], matrix[1], matrix[2] } 와도 같습니다. 원소들인 matrix[0], matrix[1], matrix[2] 는 자료형이 int * 이구요. 그러니 8 씩 차이가나는 것입니다. (코드 1 이유)

코드 4

 matrix = { matrix[0], matrix[1], matrix[2] } 와도 같으며 이 원소들의 타입은 int* 입니다. 즉, 포인터이기 때문에 또   matrix[0], matrix[1], matrix[2] 각각에 "1차원 배열"을 동적할당 받아 이 주소를 가리키게 할 수 있습니다.  그림에서도 그렇고 각 원소(포인터)에 각각 따로따로 1차원 배열을 할당받는 다는 이 설명으로 3 개의 1 차원 배열들은 서로 관련 없는 무관한 사이라고 말씀 드릴 수 있습니다. 즉, "이차원 배열"과 다르게 이중포인터에다 1차원 배열을 여러개 동적 할당받아 이차원 배열을 만드는 것은 이 행들과의 관련성은 전혀 없다는 것입니다. 

for문을 통해 matrix[0] 에 힙으로 크기 3 의 1차원 배열을 동적할당 하여 그 주소를 받았죠. 그리고 matrix[1] 에 또  힙으로 크기 3 의 1차원 배열을 동적할당 하여 그 주소를 받습니다. 이 두 1차원배열은 각각 힙으로 할당받은 메모리입니다. 이 두 1차원 배열은 서로 관련이 있을까요? 각각 따로따로 동적할당을 받았는데 꼭 matrix[0] 에 할당한 1차원 배열의 바로 뒤에 matrix[1] 에 할당한 1차원 배열이 있게된다는 보장이 없습니다. 즉, 따로 따로 동적할당 받았기 때문에 서로 관련도 없고 별개입니다. 그저 matrix 의 원소인 matrix[0], matrix[1]은 각각 동적으로 할당받은 1차원 배열의 주소를 담고 있는 포인터일 뿐입니다. 그러니 "행"을 "1차원 배열"에 대응시킬 수 있으니 행들과의 주소 차이는 전혀 규칙성이 없습니다. 이 행들은 서로 관련이 없기 떄문입니다. 메모리에서 붙어있지도 않구요. 그냥 이 3 개의 1차원 배열은 각각 따로따로 힙메모리 어딘가에 흩어져 있겠지요. 그래서 행의 차이가 20으로 나왔다는 것에 대해 고민하시지 않으셔도 됩니다. 아마 실행하실때마다 행의 차이가 다르게 나오실거에요. 제 컴퓨터에선 두 행의 차이가 3000대도 나오고 그러네요.

이와 달리 제가 위에서 설명드린 int a[2][3] = { {1,2,3}, {4,5,6} } 이런 "정적 배열'은 행끼리의 간격에서도 규칙성이 있겠죠. 메모리에선 1 2 3 4 5 6 이렇게 두 행 (=두 일차원 배열)이 연속되어 있기 때문입니다. 

nurugji님의 프로필

nurugji

질문자

2021.03.23

ㅜㅜ 그림너무좋아요