C语言如何在编译阶段打印结构体成员的偏移量 无需运行程序
编译期打印结构体成员偏移量的可行方案
你之前尝试的#pragma message + offsetof方案无法得到数值的核心原因是:#pragma message是C预处理器阶段执行的逻辑,而offsetof的数值计算要等到编译的语义分析阶段才会完成,预处理器阶段仅能将宏展开为__builtin_offsetof (struct A, b)的字符串形式,无法拿到最终的数值结果。
以下是两种不需要运行程序、也无需对大结构体做二分查找的可行方案:
方案1:负长度数组触发编译报错获取偏移量
利用C标准禁止负长度数组的规则,将偏移量取负值作为数组长度,编译器报错时会直接携带对应的数值:
#include <stddef.h> struct A { char a; char b; } __attribute__((packed)); // 数组长度为偏移量的负值,触发编译报错时会显示对应数值 char offset_of_b[-offsetof(struct A, b)];
编译输出示例:
> gcc main.c main.c:9:1: error: size of array ‘offset_of_b’ is negative (is -1) 9 | char offset_of_b[-offsetof(struct A, b)]; | ^~~~
直接取报错信息里的绝对值,就是成员b的偏移量1。
方案2:GCC error属性函数实现更直观的输出
如果你的GCC版本>=7,可以用带error属性的函数实现更贴合你预期的输出格式:
#include <stddef.h> struct A { char a; char b; } __attribute__((packed)); // 声明带error属性的占位函数,编译器遇到调用该函数时会主动报错 void print_b_offset(size_t offset) __attribute__((error("The offset of b is: "))); int main(void) { // 传入编译期常量offset作为参数 print_b_offset(offsetof(struct A, b)); return 0; }
编译输出示例:
> gcc main.c main.c: In function ‘main’: main.c:12:5: error: call to ‘print_b_offset’ declared with attribute error: The offset of b is: 12 | print_b_offset(offsetof(struct A, b)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.c:12:5: note: constant argument is ‘1’
部分更新版本的GCC会直接把参数数值拼接在error信息后面,无需额外查看note。
内容的提问来源于stack exchange,提问作者Daniel Kleinstein
相关产品推荐
相关产品推荐

