문제

내가이 구조를 가지고 있다고 가정 해 봅시다 :

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);

다른 모든 방법은 안전하지 않습니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top