2017-03-17 72 views
3

一個解決方案打印在info結構的偏移checksum場的,是使用宏typeofoffsetof如何在C中獲取嵌套結構成員的偏移量?

#include <stdio.h> 
#include <stddef.h> 
#include <stdint.h> 

typedef struct 
{ 
    struct { 
     int a; 
    } something; 

    struct { 
     int a; 
     int b; 
     int c[42]; 
     uint32_t checksum; 
     int padding[10]; 
    } info[2]; 
    // ... 
} S; 

int main(void) 
{ 
    S s; 
    printf("%lu\n", offsetof(typeof(s.info[0]), checksum)); 
    return 0; 
} 

不幸的是,typeof不規範,所以我要尋找一個更方便的方式寫上面的例子,而不必從S以外申報info

爲什麼我正在試圖做到這一點?

我有一個很大的結構,代表代表信息塊的閃存內容。每個模塊都有一個校驗和,我想檢查:

if (s.info[0].checksum != checksum(s.info[0], offsetof(typeof(s.info[0]), checksum))) { 
    printf("Oops\n"); 
} 

寫作是不可移植的,因爲typeof

+1

出於興趣,您在解決這個問題時遇到什麼問題? – Bathsheba

+0

@Bathsheba查看我的更新瞭解更多詳情 – nowox

+0

您可以隨時給結構一個標籤 –

回答

2

我不知道爲什麼你的想法(非現有標準C)typeof是必需的。這與offsetof順順當當去,如果你給結構標記(information):

#include <stddef.h> 
#include <stdint.h> 
#include <stdio.h> 

typedef struct 
{ 
    struct { 
     int a; 
    } something; 

    struct information { 
     int a; 
     int b; 
     int c[42]; 
     uint32_t checksum; 
     int padding[10]; 
    } info[2]; 
    // ... 
} S; 

int main(void) 
{ 
    printf("%zu\n", offsetof(S, info[0].checksum)); 
    printf("%zu\n", offsetof(S, info[1].checksum)); 
    printf("%zu\n", offsetof(struct information, checksum)); 
    printf("%zu\n", offsetof(S, info[0].checksum) - offsetof(S, info[0].a)); 
    return 0; 
} 

實例運行:

$ ./a.out 
180 
400 
176 
176 

BTW,don't bother with typedefs for structs.他們是無用的。你不必相信我,但你可以相信彼得範德林登。

+2

爲什麼我們必須相信彼得範德林登?這只是個人風格。我喜歡使用typedefs,因爲如果我犯了一個錯字,它會告訴我關於未聲明的標識符,而不是在代碼的某個不同部分得到一個神祕的不兼容類型的錯誤 –

+0

這非常有趣。所以'struct information'的範圍是全局的。我不知道這一點,這意味着我不能在某處聲明另一個結構信息。因此,在這種特殊情況下命名結構是一個非常糟糕的主意,因爲我可以發生衝突。 – nowox

+0

@nowox由於C標準是第一個成員,所以s和s.info [0]的開頭保證是相同的(偏移量爲0)。 – Jens

0

使用指針算術。獲取元素的地址,然後從結構的地址中減去該地址。

((unsigned char *) &(s.info[0]).checksum - (unsigned char *) &(s.info[0])) 
+0

它工作,它是便攜式的,但我覺得它比我最初的建議可讀性差 – nowox

+0

@nowox它是完全沒問題的。每個熟練的C程序員都會知道你想要什麼。如果你擔心,請記下那些小小的代碼(//獲取結構中元素校驗和的偏移量),或者將其保存在一個函數中。 – Mayazcherquoi

+0

感謝您的類型更改。有一個upvote! – Bathsheba