59.11 심사문제 관련 질문있습니다.
, 푸 푸님이 작성일단 심사문제에서 오답을 내면 나오는 답변은 다음과 같습니다.
-------------------------
표준 입력을 통해 구조체 배열의 각 요소에 값이 저장되었습니다. 이 배열을 동적으로 할당한 메모리에 복사한 뒤 배열의 모든 요소를 0으로 바꾸었습니다. 따라서 값을 출력하려면 ptr만 사용해야 합니다. ptr은 void 포인터이므로 Point3D 구조체의 형태를 모르는 상태이므로 멤버에 바로 접근할 수 없습니다. 따라서 (struct Point3D *)ptr과 같이 구조체 포인터로 변환해줍니다. ptr을 구조체 배열로 봤을 때 두 번째 요소에서 x의 값을 가져와야 하므로 ((struct Point2D *)ptr + 1)->x와 같이 포인터 연산을 사용한 뒤 화살표 연산자로 x에 접근하면 됩니다. 마찬가지로 세 번째 요소에서 z의 값은 ((struct Point2D *)ptr + 2)와 같이 접근하면 됩니다.
--------------------
이에 답변을 참조하여 result2 = *(((struct Point3D *)ptr + 2)->z); 로 답을 작성했는데 컴파일러에서 간접참조가 잘못되었다고 합니다.
어떤 부분에서 잘못되었는데 힌트를 주시면 감사하겠습니다.
그리고 오답에서 나오는 답변에서 Point2D가 아닌 Point3D로 작성되어야 정확한 답변인 것 같습니다.
Re: 59.11 심사문제 관련 질문있습니다.
, 도장_ 관리자님이 작성void *ptr로 범용 포인터로 작성되었습니다.
따라서 이 상태에서 ptr + 1 같은 포인터 연산은 할 수 없습니다. ptr + 1이라면 ptr[1]에접근하기 위한 것이지만, 지금은 할 수 없지요.
void *ptr에서 ptr의 타입은 pointer to void입니다.
pointer to void에서는 작업을 할 수 없고,
struct Point3D p[]에 접근하려면 타입을 변환하면 됩니다. p[] 배열은 *p로 전환됩니다. 배열은 C 언어 내부에서 포인터(주소)로 처리된다고 이해하면 됩니다.
(struct Point3D *)ptr은
pointer to void를
pointer to Point3D로 변경합니다.
다들 헷갈려 하는데, struct Point3D a로 선언하면
a의 타입은 struct Point3D이고
struct Point3D *b로 선언하면
b의 타입은 pointer to Point3D입니다.
책에서 포인터 관련 단원부터 포인터 구조는 그림으로 그려서 설명하고 있는데,
코드를 보고 같은 그림을 그릴 정도로 숙달되지 않았다면 포인터 이해도가 낮은 상태라는 뜻입니다.
(struct Point3D *)ptr로 타입을 변환했으면 다음은 우선순위가 낮은 +1을 처리하게 됩니다.
((struct Point3D *)ptr + 1)은 코드에서 p[1]과 동일합니다.
p[1]->z의 타입은 float이고,
마찬가지로
((struct Point3D *)ptr + 1)->z의 타입도 float입니다.
그런데 여기에 다시
*(((struct Point3D *)ptr + 1)->z)를 쓰면 포인터가 아닌 float에 *를 써서 역참조한다는 것인데 애초에 포인터가 아니므로 에러입니다.
변수 result1, result2는 float이고, 여기에 대입할 수 있는 것은 float 타입입니다.
배열은 정적할당이지만, 실제 데이터를 처리하는 코드에서는 동적할당을 더 빈번하게 사용합니다. 포인터를 이용한 메모리 할당과 배열 처리에 대해서는 반드시 숙달해야 합니다.
책을 끝낼 때쯤에는 비트맵을 아스키 아트로 변환하는 것까지 학습하면서 숙달하게 될 겁니다.