• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

포인터 이차배열 질문 드립니다.

21.01.16 01:25 작성 조회수 133

0

교수님 안녕하십니까.

c언어의 기본을 다지고자 교수님 강의를 수강하고 있는 사람입니다.

주로 사용하던 언어가 c언어는 아닌지라, 오랜만에 관련 수업을 들으니 뭔가 낯선 느낌이네요.

한가지 질문드리고 싶은 부분은 이차배열과 포인터에 관련된 부분입니다.

예를 들어, 

#define COL 3

//나머지는 생략하겠습니다.

int arr[2][COL] = { {1,2,3}, {4,5,6} };

int(*ptr_test)[COL] = arr;

if (ptr_test == ptr_test[0])

printf("same");

이 부분에서 값을 찍다보니 살짝 의아한 부분이 있습니다.

교수님 강의에도 설명되었듯 기본 배열에서 배열명이 단독으로 쓰일 경우는 포인터와 같은 역할을 하고,

예를 들어,  int arr[2] = {1, 2}; 이런 배열이 있다면 arr = &arr[0] 와 같다보니 이와 같은 의문이 들게 되었습니다.

저 위의 코드에서 arr == arr[0] ==  &arr[0] == &arr[0][0] 이고,

ptr_test == ptr_test[0]  == &ptr_test[0] == &ptr_test[0][0] 이므로

위의 조건문도 "same"을 잘 찍습니다.

실제로 메모리 주소값 또한 동일한 것은 확인을 했는데 저 부분에서 *ptr_test과 *ptr_test[0] 를 각각 찍어보면

*ptr_test는 다시 메모리 주소값이 나오고, *ptr_test[0]은 arr[0][0]값이 나오는 게 조금 이해가 가지 않습니다.

같은 메모리 주소에서 역참조한 값인데 결과가 다르다는 걸 어떤 식으로 이해하는 게 좋을까요 ? 

좋은 강의 만들어주셔서 감사합니다.

답변 4

·

답변을 작성해보세요.

2

안소님의 프로필

안소

2021.01.16

안녕하세요.

- 우선 질문자님께서 작성해주신 코드는 컴파일 오류가 나는 코드인데 "same"이 잘 나왔다고 하셔서 의아합니다. ptr_test와 ptr_test[0]이 같은 것은 맞지만 pre_test 는 int[3] 배열을 가리키는 포인터이고 pre_test[0] 은 일반 int 배열을 가리키는 포인터이기 때문에 타입이 달라 == 연산을 할 수 없기 때문입니다. 질문자님이 주신 코드만으로는 좀 의아한 부분이네요.

- arr은 원소의 자료형이 "int[3] 배열"인 길이 2의 배열이라고 생각하시면 됩니다. 즉 arr은 3길이의 int 배열의 첫번째 원소의 '주소'들을 담는 배열인 것입니다.  (그냥 int 배열과 int[3] 배열은 다른 것입니다.) ptr_test 도 "int[3]" 배열을 가리키는 포인터입니다.  자료형이 "int[3]" 인 데이터를 가리키는 포인터나 마찬가지인 것입니다. 따라서 arr[0]은 {1, 2, 3} 배열의 첫번째 원소의 주소인 &arr[0][0] 와도 같으며, arr[1]은 {4, 5, 6} 배열의 첫번째 원소의 주소인 &arr[1][0]과도 같습니다. 이는 곧 *arr[0]은 arr[0][0]와도 같다는 의미가 되겠지요. *arr은 arr의 첫번째 원소를 의미합니다. arr의 첫번째 원소는 바로 {1, 2, 3} 배열의 첫번째 원소의 주소이므로 *arr은 {1, 2, 3}의 원소인 1의 주소가 됩니다. 즉 {1, 2, 3} 배열의 이름이 곧 *arr 혹은 arr[0]가 되는 것이라고 생각하시면 됩니다. 그래서 *arr[0]은 1이 되지요. arr 값을 대입받아 arr 주소값을 가지고 있는 ptr_test도 마찬가지입니다. 

왼쪽은 int[3] 배열이 되겠고 오른쪽은 그냥 int 배열이 되겠습니다. 빨간 화살표를 보내는 부분은 화살표로 가리킨 부분의 주소를 담는 다는 의미입니다. 

실제 메모리는 이런 모습이겠네요

- 다음에 질문 주실 때는 꼭 연관 강의에서 질문 주시기를 부탁드립니다. 타임라인까지 명시해주시면 좋습니다. 질문 주시면 제가 해당 질문이 발생한 강의를 다시 돌려보며 참고해야 하는데 이렇게 질문 주시면 어떤 강의의 어떤 부분에서 질문을 주신 것인지 알 수가 없어 어렵습니다. 꼭 연관 강의에서 질문 주세요.

1

안소님의 프로필

안소

2021.01.16

- 원글 에서 작성해주셨던 " *ptr_test는 다시 메모리 주소값이 나오고, *ptr_test[0]은 arr[0][0]값이 나오는 게 조금 이해가 가지 않습니다." 이 부분은 제 그림으로 설명이 될 것 같습니다. *ptr_test는 arr[0] 일테니 { 1, 2, 3 } 배열의 주소가 나오는 것이고, *ptr_test[0] 은 이 {1, 2, 3}의 주소에 대한 역참조이니 arr[0][0]인 1 이 됩니다. 

- 배열 이름도 주소가 담겨있는 포인터와 같은 역할을 하니까 배열 이름 자체도 공간이 있을테니 &arr 와 arr 는 달라야 정상일텐데 왜 같은지에 대해 이해가 안간다는 말씀 맞을까요? 배열의 이름의 주소와 배열의 이름은 왜 같은지에 대해서요!

이건 저도 문득 궁금해져서 찾아보았는데

https://stackoverflow.com/questions/19344162/how-array-name-has-its-address-as-well-as-its-first-element-in-it

이 링크가 도움이 될 수 있을 것 같습니다. 저도 명쾌하게 와닿진 않는데 위 링크를 읽어보니 시스템상 이유인 것 같아요.

0

이원석님의 프로필

이원석

질문자

2021.01.17

안녕하세요.

참조해주신 링크 가서 읽어보니, 접근하는 관점에 대한 차이 정도로 이해하면 될 것 같네요.

친절한 답변 감사드립니다.

0

이원석님의 프로필

이원석

질문자

2021.01.16

안녕하세요.

네, 답변 감사드립니다. 

저도 위의 그림처럼 이해를 하고 있었지만, 수업을 들으면서 생각하다보니 위의 그림으로는 약간 헷갈리는 부분이 있어서요.

배열의 이름이 포인터와 같은 역할을 한다. <- 이 부분에서 보면 포인터도 하나의 변수이니,
int *ptr; 로 선언을 하고 어느 변수값을 참조할 경우,
ptr은 참조하는 변수의 주소값, 그리고 &ptr은 포인터 변수 자체의 주소값이라 같을 수가 없을텐데(자기 자신을 참조하거나 하는 경우는 제외하겠습니다.)

실제로 위와 같이 배열명으로 접근을 할 경우에는 따로 포인터처럼 메모리 상에 변수공간이 할당되는 것도 아니고
위의 예로 말씀드리자면 arr[0] = &arr[0] 이다 보니 이 부분을 어떻게 이해하는 게 조금 더 좋을지 고민입니다.

바쁘실텐데 답변 주셔서 감사드리고 위의 질문 또한 답변 기다리겠습니다.

감사합니다.