仅评估一次宏参数

时间:2010-08-30 23:33:00

标签: c gcc macros c-preprocessor

在下面的代码中,将retval传递的任何内容评估为每次使用该令牌时给出的内容。

#define _CPFS_RETURN(commit, retval) do { \
        util_cpfs_exit(commit); \
        return retval; \
    } while (false)

#define CPFS_RETURN_BOOL(retval) do { \
        _CPFS_RETURN(retval, retval); \
    } while (false)

例如,如果使用CPFS_RETURN_BOOL(inode && file_truncate(inode, len));,则会生成:

do { 
    do {
        util_cpfs_exit(inode && file_truncate(inode, len));
        return inode && file_truncate(inode, len);
    } while (0);
} while (0);

显然我不想多次执行语句inode && file_truncate(inode, len);。 如何确保在粘贴helter-skelter之前评估给定的令牌?

更新

我相信我有充分的理由在这里使用宏。在可能的情况下,将代码放入实际函数(例如 util_cpfs_exit )中,这些函数是从我正在使用的一组宏中调用的。宏根据返回类型而有所不同:在C ++中,我有明确的模板来处理这个问题。

4 个答案:

答案 0 :(得分:4)

由于您的宏在返回类型上有所不同,您可以计算retval表达式并将其存储在第一级宏内的正确类型的变量中,然后使用此变量。即:

#define CPFS_RETURN_BOOL(retval) do { \
    bool _tmp_ = retval;
    _CPFS_RETURN(_tmp_, _tmp_); \
} while (false);

如果我理解得很好,那对你的用例就足够了,对于其他用例,你可以使用函数。

在你的例子中,你会得到:

do {
   bool _tmp_ = inode && file_truncate(inode, len);
   do {
      util_cpfs_exit(_tmp_);
      return _tmp_;
   } while (0);
} while (0);

看起来很好。

PS:作为旁注,如果您始终在上述模型之后通过另一个宏间接使用_CPFS_RETURN,则无需通过do { } while (false);保护它。此外,在while(false)之后放置一个分号消除了使用它的大部分兴趣......这可能是为什么C宏是危险的并且隐藏容易陷阱的一个很好的例子。并非我不喜欢宏,恰恰相反。我来自(可能是罕见的)那些希望增强C宏以超越其当前限制以变得非常酷的人(并且不,C ++模板不是增强型宏,它们是完全不同的。)

答案 1 :(得分:2)

我建议您先评估病情。

bool val = inode && file_truncate(inode, len);

除此之外,建议可能是避免使用宏,在这种情况下它们似乎是不必要的,而是使用函数。

答案 2 :(得分:1)

编写函数而不是使用宏。在这种情况下,如果要在其中构建return语句,最好只显式编写代码,而不是依赖宏来隐藏您正在做的事情。

答案 3 :(得分:-1)

将宏更改为“静态内联”功能。在gcc中,它和宏一样快。 http://gcc.gnu.org/onlinedocs/gcc/Inline.html

相关问题