You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

说明:

  1. do { ... } while(0)是为了让宏在任何语法场景下都能正确工作(比如放在if语句后不会出现语法错误);
  2. __auto_type会自动推导ret的类型为当前函数的返回类型,只要返回类型是带error字段的结构体,就能正确初始化返回值;
  3. 调用时直接写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:23:40