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

Joh*_*ohn 3 c gcc

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

Sha*_*our 7

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));
Run Code Online (Sandbox Code Playgroud)

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

 offsets: i=0; c=4; d=8 a=16
 sizeof(struct s)=16
Run Code Online (Sandbox Code Playgroud)

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

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

更新

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

#include <stddef.h>

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 ;
}
Run Code Online (Sandbox Code Playgroud)

使用建立:

gcc -x c -std=c99 -O0 -fverbose-asm  -S main.cpp && cat main.s | grep offsetArray
Run Code Online (Sandbox Code Playgroud)

示例输出(实例):

movl    $0, -16(%rbp)   #, offsetArray
movl    $4, -12(%rbp)   #, offsetArray
movl    $8, -8(%rbp)    #, offsetArray
movl    $16, -4(%rbp)   #, offsetArray
Run Code Online (Sandbox Code Playgroud)


Joh*_*ohn 3

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

\n\n
#include <stddef.h>\n\n#define offsetof_ct(structname, membername) \\\nvoid ___offset_##membername ## ___(void) { \\\n        volatile char dummy[10000 + offsetof(structname, membername) ]; \\\n        dummy[0]=dummy[0]; \\\n}\n\nstruct x {\n        int a[100];\n        int b[20];\n        int c[30];\n};\n\noffsetof_ct(struct x,a);\noffsetof_ct(struct x,b);\noffsetof_ct(struct x,c);\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后运行:

\n\n
~/tmp> gcc tst.c -Wframe-larger-than=1000\ntst.c: In function \xc3\xa2\xe2\x82\xac\xcb\x9c___offset_a___\xc3\xa2\xe2\x82\xac\xe2\x84\xa2:\ntst.c:16:1: warning: the frame size of 10000 bytes is larger than 1000 bytes\ntst.c: In function \xc3\xa2\xe2\x82\xac\xcb\x9c___offset_b___\xc3\xa2\xe2\x82\xac\xe2\x84\xa2:\ntst.c:17:1: warning: the frame size of 10400 bytes is larger than 1000 bytes\ntst.c: In function \xc3\xa2\xe2\x82\xac\xcb\x9c___offset_c___\xc3\xa2\xe2\x82\xac\xe2\x84\xa2:\ntst.c:18:1: warning: the frame size of 10480 bytes is larger than 1000 bytes\n/usr/lib/gcc/x86_64-redhat-linux/4.5.1/../../../../lib64/crt1.o: In function `_start\':\n(.text+0x20): undefined reference to `main\'\ncollect2: ld returned 1 exit status\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

约翰

\n