포인터의 고찰.. 명확한 설명과 이해를 시켜주시면 고맙겠습니다.
제가 밑에 설명하고 있는게 맞는지 궁금합니다. 아무쪼록 C 프로그래밍의 해박한 분이 리플달아주셨으면 감사하겠습니다.
먼저 제가 궁금해하는 것은 다음의 코드입니다.
int main()
{
int a[3][2] = { {1,2}, {3,4}, {5,6} };
printf("a[0] = %d\n", a[0]);
printf("a = %d\n", a);
printf("*a = %d\n", *a);
printf("**a = %d\n", **a);
return 0;
}
실행 화면
a[0] = 1245032
a = 1245032
*a = 1245032
**a = 1
Press any key to continue
여기서 왜 a의 값과 *a의 값이 같냐는 것입니다.
*a는 1이 아니고 a와 같은 값을 출력하게 되는데 이것의 이유를 알려면 배열명은 상수포인터이니까 먼저 상수포인터의 특징을 알아야 할것 같다는 생각이 들어서 다음과 같이 생각을 하게 되었습니다.
@ 상수 포인터의 특징
상수포인터라는 것은 자신의 주소값을 가지지 않는다.
상수포인터의 주소를 출력하면 상수포인터가 가리키는 주소와 같다.
이것을 알게된 후에 저는 위에서 궁금해하던 점을 다음과 같이 이해하였습니다.
먼저 a[0], a[1], a[2]은 각각 &a[0][0], &a[1][0], &a[2][0]과 같다.
그리고 배열명 a는 a[0]을 가리킨다. 하지만 a[0]는 상수포인터이다.
위의 코드에서 배멸명 a의 타입은 int (*ptr)[2]과 같습니다.
이것은 2개 요소를 가지는 배열을 가리키는 포인터입니다.
int (*ptr)[2] = a; 라고 했을때
printf("ptr = %d\n", ptr);
// a[0]라는 상수포인터의 주소를 출력, 상수포인터의 특징에 따라 a[0]의 주소는 a[0]가 가리키는 주소와 같으므로 &a[0][0]이 출력된다.
printf("*ptr = %d\n", *ptr);
// a[0]가 가리키는 주소를 출력, 따라서 &a[0][0]가 출력된다.
printf("**ptr = %d\n", **ptr);
// *ptr은 &a[0][0]이므로 **ptr은 a[0][0]의 값을 출력하게 된다.
과연 이렇게 이해하는게 맞습니까?
상수포인터의 특징을 제 나름대로 위에서 정의해봤는데 저렇게 생각해도 됩니까?
이렇게 이해하는게 틀리다면 어떻게 이해해야 하나요?
글 읽어 주셔서 감사하고요.. 좋은 답변 바랍니다.
추가적으로 또 한가지 궁금한 것은 g++에서는 안되지만 gcc에서는 다음의 코드가 warning이 뜨지만 실행이 되는데
int **dptr = a;
printf("dptr = %d\n", dptr);
printf("*dptr = %d\n", *dptr); // 1이 출력됨
gcc에서 int **dptr = a와 같이 형 변환이 맞지 않는데 이것을 허용하는데 C 프로그래머가 이러한 것은 하지않도록 주의해야하는 것인가요?
너무 훌륭해서 답글에 쓸 말이 없지만
그냥 지나가다 댓글 답니다.
a와 *a 와의 차이점은
a+1 , *a + 1 이라고 했을 때 나타나고
각각
a+1 == &a[1][0] 이고
*a+1 == &a[0][1] 입니다
둘러보다가~
코딩한지 오래되서 가물가물한 포인터를 정리하는중에 비슷한 질문같아서요..
그냥 기록차 적어놓습니다.
a는 2차원배열의 첫번째요소의 주소이고, *a는 a[0]과 같아서 배열의 0번째 행을 나타내므로 해당 주소는 마찬가지로 a, *a, a[0] 모두가 같습니다.
그러나 실제 서로 같다고 할수는 없는것이 각각에 대해서 sizeof를 해보면 a는 배열전체의 요소인 24바이트를, *a와 a[0]은 열이 2개이므로 8바이트를 가리킵니다.
그리고 int **ptr 은 1차원 포인터배열의 변수이므로 2차원배열인 a를 대입하면 형이 틀리다고 warning이 납니다.
옳바르게 하려면 int (*ptr)[2] 라고 2차원 포인터변수를 선언하고 대입하는것이 맞습니다.
댓글 달기