为何GCC的typeof()无法通过宏字符串化获取实际类型名称?
为什么宏字符串化无法获取typeof推导的类型名
核心原因:C语言的处理阶段是严格分层的
C代码的编译流程按固定顺序执行,预处理器是最先运行的阶段,预处理器完全不懂C语言语法、更没有类型推导能力,它只做纯文本层面的token替换、宏展开、字符串化操作;而typeof是编译器语义分析阶段才会处理的运算符,它的类型推导结果,在预处理器运行时根本还不存在。
你的代码实际展开逻辑
你写的GET_STRING宏的字符串化操作,只会把传入的token序列原封不动转成字符串,不会做任何语义解析:
#define GET_STRING(s) #s #define example(input) \ do { \ char test[20] = GET_STRING(typeof(input)); \ printf(test); \ } \ while(0)
当你调用example(某个变量)时,预处理器的处理步骤是:
- 把宏参数
input替换成你传入的变量名token,此时GET_STRING的入参是typeof(你的变量名)这一串纯文本token - 执行
#s字符串化,直接把这串token转成字面量字符串"typeof(你的变量名)" - 预处理器工作全部完成,之后编译器才开始跑语义分析,计算
typeof对应的实际类型——但这时候字符串早就生成完了,根本不可能把推导结果塞回去。
你提到GET_STRING(int)能正常得到"int",本质是因为int本身就是预处理器阶段就存在的原始token,不需要编译器后续做任何推导计算,和typeof这种需要编译器计算结果的运算符完全不是一回事。
可行的解决方案
纯标准C+预处理器不可能实现这个需求,必须依赖编译器提供的扩展能力,常见方案有两种:
- 高版本GCC/Clang(GCC 12+、Clang 15+)可以直接使用内置函数
__builtin_typename,它能在编译期返回类型对应的常量字符串:#define typeof_str(x) __builtin_typename(__typeof__(x)) // 调用示例:printf("%s", typeof_str(123)); 会直接输出"int" - 低版本编译器可以借助
__PRETTY_FUNCTION__这个编译器内置宏,它会在编译期生成包含当前函数签名、参数类型信息的字符串,你可以通过辅助宏提取其中的类型名部分,本质也是利用编译器已经完成类型推导后生成的字符串常量。
注意:C23标准虽然把
typeof纳入了标准语法,但没有提供任何编译期获取类型名字符串的标准接口,所以不存在跨编译器的纯标准实现方案。
内容的提问来源于stack exchange,提问作者Kyle Ponikiewski
相关产品推荐
相关产品推荐

