2017-03-17 69 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