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

C语言单元测试宏如何打印作为参数的函数调用返回值

问题原因

你用到的STR(x)是C预处理器的字符串化运算符,只会在预处理阶段把宏参数的字面代码直接转换为C字符串,完全不会执行任何运行时求值逻辑。所以当你传入函数调用作为参数时,它直接把my_fn_that_returns_false()这段代码转成了字符串输出,和运行时的函数返回值没有任何关联。

你原本的测试逻辑中(LHS) != (RHS)判断是正常求值的,但是打印逻辑只输出了表达式的字面字符串,没有输出运行时结果,这就是问题的核心原因。

修复方案

我们可以在宏中先对LHS、RHS做一次求值并存入临时变量,既可以避免重复执行表达式带来的副作用(比如函数内部修改全局变量,多次执行结果不一致),也能拿到实际的运行时结果用于打印。
如果你的测试场景以整型(布尔、int、枚举等可隐式转为int的类型)为主,可以用以下修改后的实现:

#include <stdio.h>

#define STR(x) #x

#define TEST_COMPARE_EQ(TestName, LHS, RHS) \
do {                             \
    // 先求值存入临时变量,GCC/Clang原生支持typeof,C23标准已正式纳入该关键字
    typeof(LHS) lhs_val = (LHS); \
    typeof(RHS) rhs_val = (RHS); \
    if (lhs_val != rhs_val) {              \
      printf("[Test: %s] --- Failed at line %d in file %s\n", TestName, __LINE__, __FILE__); \
      // 可根据需要选择是否保留原始表达式打印
      printf("Got value: %d (expression: %s)\n", (int)lhs_val, STR(LHS)); \
      printf("Expected value: %d (expression: %s)\n", (int)rhs_val, STR(RHS)); \
    }                                        \
    else {                                   \
      printf("[Test: %s] --- Passed\n", TestName); \
    }\
  } while (0)

如果需要支持浮点、字符串等更多类型,可以结合C11的_Generic关键字自动匹配对应类型的打印格式符。

效果示例

对于你给出的测试用例:

TEST_COMPARE_EQ("PrintingDoesNotWork", my_fn_that_returns_false(), true);

假设my_fn_that_returns_false()返回0、true定义为1,失败时的打印结果为:

[Test: PrintingDoesNotWork] --- Failed at line xx in file test.c
Got value: 0 (expression: my_fn_that_returns_false())
Expected value: 1 (expression: true)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:06:04