C语言能否提取函数返回类型?如何实现类似absl::StatusOr的宏?
问题描述
我用GCC编译C程序时,尝试通过__PRETTY_FUNCTION__、__FUNCTION__、__func__这些宏获取函数返回类型,但它们只能输出函数名(比如main),拿不到int这类返回类型。另外,我想实现一个通用的错误处理宏CHECK,不用手动指定返回类型,能适配所有带error字段的结构体,类似C++里absl::StatusOr的功能,具体场景代码如下:
typedef struct { // ... // A的专属数据 uint32_t error; } StructA; typedef struct { // ... // B的专属数据 uint32_t error; } StructB; typedef struct { // ... // C的专属数据 uint32_t error; } StructC; #define CHECK(data, ReturnType) { if (data.error) { return (ReturnType) { .error = data.error }; } } // 返回成功值或错误码 StructC build_c() { StructA a = ...; CHECK(a, StructC); // 不想手动写StructC StructB b = ...; CHECK(b, StructC); // 不想手动写StructC return (StructC) { .data = a.data + b.data }; }
请问这两个需求是否可行?
解答
一、获取函数返回类型:可行,但依赖GCC非标准扩展
标准C的__func__、__FUNCTION__确实只返回函数名;__PRETTY_FUNCTION__的字符串输出里虽然包含返回类型(比如StructC build_c()),但解析字符串不可靠,不同GCC版本的输出格式可能变化。
更可靠的方式是利用GCC的__typeof__扩展,推导当前函数的返回类型:
// 定义宏获取当前函数的返回类型 #define GET_CURRENT_RETURN_TYPE() __typeof__((*((__typeof__(&__func__))NULL))())
原理是:通过__typeof__(&__func__)得到当前函数的指针类型,再通过(*指针)()推导函数的返回类型。这个方法仅适用于GCC,不属于C标准。
二、实现通用CHECK宏:完全可行,无需手动指定返回类型
利用GCC的__auto_type扩展(GCC 4.9及以上版本支持),可以让宏自动推导当前函数的返回类型,无需手动传入ReturnType参数。修改后的宏如下:
#define CHECK(data) \ do { \ if ((data).error != 0) { \ __auto_type ret = { .error = (data).error }; \ return ret; \ } \ } while(0)
说明:
do { ... } while(0)是为了让宏在任何语法场景下都能正确工作(比如放在if语句后不会出现语法错误);__auto_type会自动推导ret的类型为当前函数的返回类型,只要返回类型是带error字段的结构体,就能正确初始化返回值;- 调用时直接写
CHECK(a)、CHECK(b)即可,无需指定返回类型,完全适配所有带error字段的结构体返回类型的函数。
如果需要兼容更早版本的GCC(<4.9),可以用__typeof__结合函数指针推导返回类型:
#define CHECK(data) \ do { \ if ((data).error != 0) { \ typedef __typeof__((*((__typeof__(&__func__))NULL))()) return_type; \ return (return_type){ .error = (data).error }; \ } \ } while(0)
内容的提问来源于stack exchange,提问作者mercury0114
相关产品推荐
相关产品推荐

