c - 如何在编译时打印结构成员的偏移量?

标签 c gcc

给定一个结构,例如:

struct A {
    char a;
    char b;
} __attribute__((packed));
我想要 b 的偏移量(在这个例子中,1)在编译时打印的结构中 - 我不想运行程序并调用类似 printf("%zu", offsetof(struct A, b)); 的东西因为在我的平台上打印非常重要。我希望编译器本身打印偏移量,例如:
> gcc main.c
The offset of b is 1

我尝试了一些使用 #pragma message 的方法和 offsetof ,我最接近的是:
#define OFFSET offsetof(struct A, b)
#define XSTR(x) STR(x)
#define STR(x) #x

#pragma message "Offset: " XSTR(OFFSET)
只打印:
> gcc main.c
main.c:12:9: note: #pragma message: Offset: __builtin_offsetof (struct A, b)
它不打印数字偏移量。可以在编译时使用 _Static_assert 对偏移量进行二进制搜索。 - 但我真正的结构很大,这可能会变得有点麻烦。

最佳答案

我怀疑声明的约束“我希望由编译器本身打印偏移量”是一个 XY 问题,我们只需要由用于构建的系统上的构建工具打印偏移量,而不是由编译器专门打印。
在这种情况下,GCC 和 Clang 有能力 include arbitrary text in their assembly output并在该文本中包含各种数据操作数,包括结构偏移的立即数。
在任何函数中,包括以下几行:

#if GenerateStructureOffsets
    __asm__("# offsetof(struct A, b) = %c0" : : "i" (offsetof(struct A, b)));
#endif
然后用开关编译 -DGenerateStructureOffsets-S .编译器会生成一个名为 SourceFileName.s 的文件,您可以使用 -o Name如果需要,可以给它一个不同的名字。
然后grep "## offsetof" Name会找到这一行,显示如下内容:
## offsetof(struct A, b) = 1

那么你可以使用sed或其他工具来提取值(value)。
__asm__ , "i"说生成一个“立即”操作数。 (offsetof(struct A, b))随之而来的是它应该具有的值(value)。在第一个带引号的字符串中,%c0替换为该操作数的值。0指示要替换的操作数——如果后面列出了多个操作数 __asm__ ,它们的编号为 0、1、2、3,依此类推。 (也有命名它们的机制,这里没有显示。)通常,%0将替换为适合目标汇编语言的立即操作数形式,例如 $1#1 .然而,c修饰符说使用裸常量,所以替换文本只是值,在这种情况下 1 .

关于c - 如何在编译时打印结构成员的偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69208830/

相关文章:

c - strstr:使用不同版本的 gcc 时行为不同

c++ - G++ 显示关于未定义命名空间的错误

c++ - 在 g++ 中使用版本脚本导出 c++ 构造函数

c - 使用gcc编译C源代码时的问号

c - 结构数组的初始化会初始化单个元素的所有成员,为什么?

c - GDB 输入文件等

c - 将标准输出/输入/错误重定向到/从文本框

c - 加载了 dlopen 的共享库是否会自动关闭?

c - 如何将字符串分配给 C 中的字符指针?

c - 如何获取调用函数的名称?