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

如何创建自动检测类型并打印数值的宏?EVAL_TYPE_FORMATER实现求助

适配多类型的assert_equal宏格式字符串实现问题

现有代码

assert_equal宏

#define assert_equal(x, y) do {\
    typeof(x) evalx = x;\
    typeof(y) evaly = y;\
    _assert(evalx == evaly, __LINE__, __FILE__,\
        EVAL_TYPE_FORMATER(evalx)" != "EVAL_TYPE_FORMATER(evaly), evalx, evaly\
    )\
} while (0)

_assert函数原型

void _assert(bool condition, size_t line, const char* file, char* format, ...);

尝试过的方案及问题

方案1:#if + typeof(失败)

试图用预处理器条件判断类型,但宏展开阶段#if无法处理typeof的动态类型结果,编译直接报错:

#define EVAL_TYPE_FORMATER(exp)\
    #if typeof(exp) == char ||\
        typeof(exp) == short ||\
        typeof(exp) == int\
        "%d"\
    #elif typeof(exp) == long\
        "%ld"\
    ...

方案2:_Generic(拼接失败)

改用C11的_Generic做编译期类型匹配,但因宏外层多加了括号,导致返回的格式字符串无法与相邻字面量自动拼接,编译失败:

#define EVAL_TYPE_FORMATER(exp) (_Generic((exp), \
        char: "%d", \
        short: "%d", \
        int: "%d", \
        long: "%ld", \
        ...
    ))

更优解决方案

修正_Generic宏写法(去掉多余括号)

C语言支持相邻字符串字面量自动合并,只需去掉EVAL_TYPE_FORMATER宏外层的括号,让_Generic直接返回字符串字面量,即可参与拼接:

#define EVAL_TYPE_FORMATER(exp) _Generic((exp), \
    char: "%d", \
    short: "%d", \
    int: "%d", \
    long: "%ld", \
    long long: "%lld", \
    unsigned char: "%u", \
    unsigned short: "%u", \
    unsigned int: "%u", \
    unsigned long: "%lu", \
    unsigned long long: "%llu", \
    float: "%f", \
    double: "%lf" \
)

此时EVAL_TYPE_FORMATER(evalx)" != "EVAL_TYPE_FORMATER(evaly)会被编译器自动合并为完整格式字符串,比如当evalx为int、evaly为long时,最终会生成"%d != %ld",可直接传入_assert函数使用。

进阶:封装类型匹配逻辑(提高可维护性)

如果需要频繁复用类型格式映射,可以把_Generic的类型匹配逻辑抽成独立宏,减少重复代码:

#define TYPE_FORMAT(exp) _Generic((exp), \
    char: "%d", \
    short: "%d", \
    int: "%d", \
    long: "%ld", \
    long long: "%lld", \
    unsigned char: "%u", \
    unsigned short: "%u", \
    unsigned int: "%u", \
    unsigned long: "%lu", \
    unsigned long long: "%llu", \
    float: "%f", \
    double: "%lf" \
)

#define assert_equal(x, y) do {\
    typeof(x) evalx = x;\
    typeof(y) evaly = y;\
    _assert(evalx == evaly, __LINE__, __FILE__,\
        TYPE_FORMAT(evalx) " != " TYPE_FORMAT(evaly), evalx, evaly\
    )\
} while (0)

补充说明

  • 该方案依赖C11及以上标准的_Generic特性,需确保编译器支持(如GCC 4.9+、Clang 3.1+、MSVC 2015+)。
  • 可根据实际需求扩展_Generic中的类型映射,覆盖更多基础类型或自定义typedef类型。

内容的提问来源于stack exchange,提问作者Tenobaal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:20:31