一种在函数调用中定义新变量的方法

A way around defining new variables in function calls

我有一个在我的代码中经常调用的函数 dangerous(GEN x),其中 GEN 是一个 typedef。出于调试目的,我想将 checkSafe 添加到此函数的所有实例中,例如

#ifdef DEBUG
  #define dangerous(x) GEN __x = (x); if(checkSafe(__x)) dangerous(__x)
#endif

但我担心这可能无法按预期工作。做这样的事情的正确方法是什么?该函数使用过于频繁,无法单独检测每次使用,并且不希望在调试模式之外进行检查(出于各种原因)。

注意事项/注意事项:

  1. 同时使用同名的宏和函数。虽然它可以生成有效的 C,但您必须 1) 采取额外的预防措施以避免不必要的扩展(总是在宏之前定义函数,或者将函数名称括在 parentheses 在定义时)和 2) 仔细检查该函数的每次使用是否还包括您的检测代码。

解决方法:将原来的函数重命名为_dangerous.

  1. 在各种情况下使用宏:
    • if 中只有一条语句:if (foo) dangerous(x);
    • 来自 parent ifelseif (foo) dangerous(x); else bar();
    • 将变量泄漏到 parent 命名空间时可能会造成破坏:GEN __x = 5; dangerous(__x);.

解决方案: 将宏包含在类似 do { ... } while(0).

的结构中
  1. 您必须考虑复制时的任何副作用,例如资源分配或 CPU 密集操作(因为 GEN 是 typedef,这可能不是问题)。

最后,您可能还想在 checkSafe 失败时进行投诉,例如通过记录错误消息,甚至中止程序。

将以上内容放在一起,您将像这样检测函数:

#ifdef DEBUG
  #define dangerous(x) do { \
    GEN __x = (x);          \
    if (checkSafe(__x))     \
      _dangerous(__x);      \
    else                    \
      complainAbout(__x);   \
  } while(0)
#else
  #define dangerous _dangerous
#endif
  1. 如果 dangerous() return 是您要使用的值(例如 int)。

解决方案: 定义一个函数来检测您的原始函数并向上传递 return 值:

#ifdef DEBUG
  static inline int dangerous(GEN x) {
    if (checkSafe(x))
      return _dangerous(x);
    complainAbout(x);
    return ERROR_CODE;
  }
#else
  #define dangerous _dangerous
#endif