문제
내가이 구조를 가지고 있다고 가정 해 봅시다 :
typedef struct nKey {
int num;
widget* widget;
} NUMBER_KEY;
그리고 기능 :
void dialKey(widget* widget) {
// Need to print 'num' of the struct that this widget resides in
}
이것을 달성하려면 어떻게해야합니까? 나는 다음과 같은 것을 시도했다.
printf("%d", * (int *) widget - sizeof(int)); // Failure.org
편집 : 전달 된 위젯이 실제로 숫자 _key struct의 구성원이라고 가정하는 것이 안전합니다.
편집 : 다른 방법이 아닌 문제에 대한 해결책을 찾고 있습니다.
해결책
다이얼 키로 전달되는 widgit **가 아닌 widgit*만으로도 원하는 것을 할 수있는 방법이 없습니다 (Widgit* 값은 숫자 _key struct와 관계가 없습니다). 당신이 정말로 의미한다고 가정합니다.
void dialKey(widget** ppWidget)
{
// Need to print 'num' of the struct that this widget resides in
}
Microsoft는 이러한 유형의 일을하는 데 멋진 매크로를 가지고 있습니다 (C에서 일반적으로 링크 된 목록을 조작하는 루틴을 가질 수 있도록 도와줍니다).
#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
당신은 이것을 그렇게 사용할 수 있습니다 :
NUMBER_KEY* pNumberKey = CONTAINING_RECORD( *ppWidgit, NUMBER_KEY, widgit);
printf( "%d", pNumberKey->num);
다른 팁
Michael이 그의 대답에서 설명 하듯이, 포인터 그래프를 "걸어 갈"방법이 없기 때문에 주어진 제약 조건으로 할 수 없습니다. 일을 더 명확하게하기 위해, 객체 다이어그램 (OOP 의미가 아닌 C 용어)을 그려 드리겠습니다.
+- NUMBER_KEY --+
| ... | points to
| widget field -+-----------+
| ... | |
+---------------+ | + widget +
+-->| ... |
| ... |
+-->| ... |
| +--------+
points to |
[widget argument]-----------+
화살표를 주목하십시오. 그들은 단방향입니다 - 당신은 포인터에서 뾰족한 값으로 "걸을 수 있지만"다시 "걸을 수는 없습니다". 그래서 당신은 연기 할 수 있습니다 widget
당신의 기능에 대한 논증 widget
물체이지만 일단 거기에 있으면 다른 사람을 포함하여 누가 다른 사람을 말할 방법이 없습니다. NUMBER_KEY
스트러크. 생각해보십시오 : 만약 당신이 똑같이 12 개의 다른 포인터를 가지고 있다면? widget
, 그들 중 일부는 다른 것입니다 NUMBER_KEY
사물? 내면의 모든 포인터 목록을 유지하지 않고 어떻게 추적 할 수 있습니까? widget
물체? 실제로 이것을 필요로한다면, 그것은 당신이해야 할 일입니다 - widget
소유권을 가리 킵니다 NUMBER_KEY
.
구조물의 메모리 레이아웃은 컴파일러에 의해 정의되며 코드는 구조물 멤버 사이에 0 바이트 패딩이있는 경우에만 작동합니다. 일반적으로 이것은 권장되지 않습니다. B/C 0 바이트 패딩은 대부분의 프로세서의 표준 읽기 크기에 걸쳐 구조물 오버레이를 갖습니다.
문제에 대한 유용한 매크로 :
#define GET_FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
#define GET_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
예시:
NUMBER_KEY key;
key.num = 55;
int nOffSetWidget = GET_FIELD_OFFSET( NUMBER_KEY, widget);
int *pKeyNumAddress = (int *) &(key.widget) - nOffSetWidget );
printf("%d", * pKeyNumAddress ); // Should print '55'
C 표준 정의 offsetof()
매크로 (정의 stddef.h
헤더), 귀하의 경우에 편리합니다.
#include <stddef.h>
void DialKey(widget** foo) {
printf("%d", *((char *)foo - offsetof(struct nKey, widget)));
}
통과해야합니다 주소 값이 아닌 구조물 필드의!
가장 안전한 솔루션은 위젯의 관련 NKE 구조에 대한 포인터를 유지하는 것입니다.
printf("%d", widget->myKey->num);
다른 모든 방법은 안전하지 않습니다