给定一个结构,例如:
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/