仅评估宏参数一次

发布于 2024-09-16 18:40:11 字数 842 浏览 8 评论 0原文

在下面的代码中,无论作为 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); 多次。 如何确保在乱七八糟地粘贴之前对给定的标记进行评估?

更新

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

In the following code, whatever is passed as retval is evaluated as given for every use of that token.

#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)

For example given the use CPFS_RETURN_BOOL(inode && file_truncate(inode, len));, this is generated:

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

Evidently I don't want to execute the statement inode && file_truncate(inode, len); more than once.
How can I ensure that the given tokens are evaluated before being pasted helter-skelter?

Update

I believe I have good reason to use macros here. Where possible, code is put into real functions (such as util_cpfs_exit) which are invoked from a set of macros I'm using. The macros vary based on the return type: in C++ I'd have explicit templates to handle this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

两个我 2024-09-23 18:40:11

由于宏的返回类型不同,您可以计算 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++ 模板不是增强的宏,它们是完全不同的东西)。

As your macro vary on the return type, you can evaluate the retval expression and store it in a variable of the right type inside the first level of macro then use this variable. ie:

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

If I understand well, that should be enough for your use case, and for other use cases you can use functions.

In your exemple you'll get:

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

Looks fine.

PS: as a sidenote if you always use _CPFS_RETURN indirectly through another macro following the above model, there is no need to protect it by a do { } while (false);. Also, putting a semi-colon after the while(false) removes most of the interest of using it... that may be a good example of why C macros are dangerous and hides easy pitfalls. Not that I dislike macros, quite the contrary. I'm from the (probably rare) kind of people that would prefer C macros to be enhanced to bypass their current limitations to become really cool (and no, C++ templates are not enhanced macros, they are something completely different).

青萝楚歌 2024-09-23 18:40:11

我建议您先评估一下病情。

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

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

I would recommend that you evaluate the condition first.

i.e.

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

Other than that may advice would be to steer well clear of macros, they seem unnecessary in this instance, use functions instead.

颜漓半夏 2024-09-23 18:40:11

编写函数而不是使用宏。在这种情况下,如果您想要构建一个 return 语句,您可能最好只显式编写代码,而不是依赖宏来隐藏您正在执行的操作。

Write a function instead of using a macro. In this case, where you want to build a return statement in, you might be better off just writing the code explicitly instead of relying on a macro to hide what you're doing.

梨涡少年 2024-09-23 18:40:11

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

Change the macro to a "static inline" function. In gcc, it's as fast as a macro.
http://gcc.gnu.org/onlinedocs/gcc/Inline.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文