|
evergreen 님이 쓰신 글 :
: 오류가 날 것 같은 코드 였는데, 확인해 보니 그렇지 않군요.
:
: typedef struct{
: int a;
: int b;
: } c;
:
: (unsigned long)&((c*)0)->b;
: 에서 &, ->의 연산자 우선순위의 혼돈을 피하기 위해
: (unsigned long) &(((c*)0)->b);
: 로 바꾸고, 이것을 다시 분리하면
:
: c *p1 = (c *) 0;
: int *pn = &(p1->b); // 여기서 p1을 참조하므로 오류가 발생될 줄 알았는데 확인해 보니 아니군요. OTL...
: Caption = (int) pn; // 결과 : 4
:
: 이것의 어셈블리 코드를 보면
:
: c *p1 = (c *) 0;
: // xor edx, edx
: // mov [ebp-0x70], edx p1 <-- 0을 넣습니다.
:
: int *pn = &(p1->b);
: // mov ecx, [bp-0x70]; ecx <-- p1의 값을 불러옵니다.
: // add ecx, 0x04 ecx <-- b의 위치(4)를 더합니다.
: // mov [ebp-0x74], ecx pn <-- ecx
:
: 하지만
: int b2 = p1->b;
: 를 추가시
: // mov eax, [bp-0x70]; eax <-- p1의 값을 불러옵니다.
: // mov edx, [ebp + 0x04] edx <-- p1->b의 값을 구함 (여기서 Access violation 오류 발생)
: // mov [ebp - 0x78], edx b2 <-- p1->b의 값 저장.
: 와 같이 되어 오류가 발생됨.
:
: 결론은 신성기 님이 말씀하신데로 메모리를 줄이고, 실행속도 등을 향상시키기 위한 것이라고
: 판단됩니다.
한가지만 덧붙인다면, 실제 저값은 컴파일러에 의해 0x04라는 상수값으로 치환됩니다.
(이 내용은 optimized code의 assembler code를 보면 알 수 있습니다. 혹시나 해서 방금 BCB6으로 확인했습니다.)
만일 인스턴스가 생긴다면 상수값의 치환이 아니라 evergreen님께서 말씀하신 위의 코드가 적용이 되겠지요.
인스턴스를 만들지 않고, 절대번지를 응용하는 내용은 다분히 컴파일러효율(code optimization)을 믿기때문에 가능한 겁니다.
사람이 판별하기는 매우 복잡하지만요...
(** 한가지 의미없는 딴지 하나더, "우선순위의 혼돈을 피하기 위해"라고 표현하셨는데요, 여기서 "혼돈"은 "혼동"으로 표기하셔야 합니다. 정확한 뜻의 차이는 사전을 참조하시면 될 겁니다. 우리말 표현에 좀 민감한 편이라 무례함을 무릅쓰고 지적합니다. 너그러운 이해 바랍니다. **)
:
: - heredity -
:
:
: ssb 님이 쓰신 글 :
: : typedef struct{
: : int a;
: : int b;
: : }c;
: :
: : (unsigned long)&((c*)0)->b; //<-이게 의미하는게 b의 위치를 말하는거 같은데 이해가 잘 안되네요.
|