baraba6u   2년 전

C언어입니다.


둘다 동일한 포인터 인데 왜 배열의 이름만 배열 크기를 반환하나요?,,


둘다 포인터 크기를 반환해야 일관된것 아닌가요?..


동일한 종류의 포인터에도 차이가 있는건가요?

gallopsys   2년 전

포인터는 배열을 가리킬 순 있지만, 그렇다고 해서 배열 = 포인터는 아님에 유의하셔야 합니다. int x;가 있으면 int *px = &x;로 일반 변수를 가리킬 수도 있으니까요.


참고로 말해서 배열은 그 자체로 고유한 자료형을 가집니다. 예를 들어 위에 올려주신 소스코드에서 int 배열 arr는 엄밀히 말하면 int *가 아닌 int[8]이라는 자료형을 가집니다. 즉, 배열이라는 건 말 그대로 하나의 자료형과 같은 거라고 보면 됩니다.

혹시 확인해보고 싶으시면 printf("%d\n", sizeof(int[8]));을 입력해보시면 동일하게 printf("%d\n", sizeof arr);와 같은 값을 내뱉는다는 걸 확인하실 수 있습니다.

또 다른 예를 들어 int x[3][2];라는 2차원 배열이 있다면, 이 배열은 int[3][2]라는 자료형을 가지는 셈이 되겠지요? char str[20000];이라는 건 char[20000]이라는 자료형을 가지고 있는 거겠구요.

여기서 확인할 수 있는 사실은 "배열"이라는 것은 배열의 베이스 주소(첫 번째 원소의 시작지점)배열의 크기를 정보로 가진다는 것입니다. 이 사실은 위의 sizeof 연산자를 통해서 확인해볼 수 있었죠.


포인터로 배열을 가리키게 되면 문제가 생깁니다. 포인터는 말 그대로 "주소값을 저장하고 있는 변수"인데요. 말 그대로 "주소"만 저장하고 있기 때문에 배열을 가리키게 되면 "주소"만 가리키게 됩니다.


위에서 배열은 "배열의 베이스 주소" 뿐만 아니라 "배열의 크기"도 정보로 가짐을 말씀드렸습니다. 포인터가 4바이트(0x00000000~0xFFFFFFFF의 주소대역폭을 가리킬 수 있으므로)의 값을 가지므로 위의 코드에서는 포인터가 4바이트를 가진다는 것을 보여주는 것이죠.

이를 다른 말로 "배열이 포인터로 붕괴되었다(Arrays decaying into pointers)"라고도 합니다.


좀 이 개념이 어렵긴 하지만, 조금 더 설명을 드리면 배열을 포인터로 넘길 때, 항상 1차원씩 붕괴 과정을 거치게 됨에 유의하셔야합니다.

예를 들어 1차원 double[4] 배열인 double xz[4];가 있다고 하죠. 이를 포인터 변수로 double *pxz = xz; 이렇게 넘겨주게 되면, xz의 배열의 크기(4)에 대한 정보는 날아가고 1차원 배열 xz의 베이스 주소만 남게 됩니다. 즉, 포인터 변수 pxz는 xz의 첫 번째 원소를 가리키게 되는 것이죠.

2차원 배열 short ary[10][15];가 있다고 해봅시다. 이를 포인터로 넘겨주려면 short(*pAry)[15] = ary;와 같이 해준다는 걸 볼 수 있는데, 이 때 유의하셔야 할 것은 pAray가 short **를 가리키는 포인터가 아닌, short[15] *를 가리키는 포인터라는 사실에 유념하셔야 합니다.

즉, short[15]의 자료형을 갖는 포인터를 가리킨다는 소리죠. 위와 같이 short[10][15]라는 자료형은 포인터를 통해 short[15] *로 붕괴되었음을 볼 수 있습니다.


baraba6u   2년 전

친절한 답변 감사합니다!!

댓글을 작성하려면 로그인해야 합니다.