有没有办法在编译时确定成员偏移量?

我发现我在调试时花了很多时间试图确定结构的成员偏移量。 我想知道是否有一种快速的方法来确定编译时大型结构中成员的偏移量。 (注意:我知道创建编译时断言的几种方法,即偏移量在给定范围内,我可以对正确的值进行二进制搜索,但我正在寻找更高效的东西)。 我正在使用一个相当新版本的gcc来编译C代码。

offsetof是你想要的,它编译时间。 C99标准草案第7.17共同定义3段说:

offsetof(type,member-designator)

它扩展为一个整数常量表达式,其类型为size_t,其值是以字节为单位的偏移量[…]

上面链接的手册页有以下示例代码,它演示了它的用法:

 struct s { int i; char c; double d; char a[]; }; /* Output is compiler dependent */ printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n", (long) offsetof(struct s, i), (long) offsetof(struct s, c), (long) offsetof(struct s, d), (long) offsetof(struct s, a)); printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s)); 

样本输出,可能会有所不同:

  offsets: i=0; c=4; d=8 a=16 sizeof(struct s)=16 

对于引用, 常量表达式将在6.6常量表达式中介绍 ,第2节说:

可以在转换期间而不是运行时期间评估常量表达式,并且因此可以在常量可以在任何地方使用。

更新

从OP中澄清后,我想出了一个使用-O0 -fverbose-asm -Sgrep的新方法,代码如下:

 #include  struct s { int i; char c; double d; char a[]; }; int main() { int offsetArray[4] = { offsetof(struct s, i ), offsetof( struct s, c ), offsetof(struct s, d ), offsetof(struct s, a ) } ; return 0 ; } 

构建使用:

 gcc -xc -std=c99 -O0 -fverbose-asm -S main.cpp && cat main.s | grep offsetArray 

示例输出( 实例 ):

 movl $0, -16(%rbp) #, offsetArray movl $4, -12(%rbp) #, offsetArray movl $8, -8(%rbp) #, offsetArray movl $16, -4(%rbp) #, offsetArray 

好的,在这里回答我自己的问题:注意:我想在编译时确定偏移量,也就是说,我不想运行代码(我也可以只编译我需要的文件,而不是整个系统):以下内容可以为有兴趣的人剪切和粘贴:

 #include  #define offsetof_ct(structname, membername) \ void ___offset_##membername ## ___(void) { \ volatile char dummy[10000 + offsetof(structname, membername) ]; \ dummy[0]=dummy[0]; \ } struct x { int a[100]; int b[20]; int c[30]; }; offsetof_ct(struct x,a); offsetof_ct(struct x,b); offsetof_ct(struct x,c); 

然后运行:

 ~/tmp> gcc tst.c -Wframe-larger-than=1000 tst.c: In function ‘___offset_a___’: tst.c:16:1: warning: the frame size of 10000 bytes is larger than 1000 bytes tst.c: In function ‘___offset_b___’: tst.c:17:1: warning: the frame size of 10400 bytes is larger than 1000 bytes tst.c: In function ‘___offset_c___’: tst.c:18:1: warning: the frame size of 10480 bytes is larger than 1000 bytes /usr/lib/gcc/x86_64-redhat-linux/4.5.1/../../../../lib64/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: ld returned 1 exit status 

然后我减去10000以获得偏移量。 注意:我尝试将#pragma GCC diagnostic warning "-Wframe-larger-than=1000"到文件中,但它不喜欢它,因此必须在命令行中指定它。

约翰

这应该做:

 #define OFFSETOF(T, m) \ (size_t) (((char *) &(((T*) NULL)->m)) - ((char *) ((T*) NULL))) 

这样叫:

 size_t off = OFFSETOF(struct s, c);