仅评估宏参数一次
在下面的代码中,无论作为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
由于宏的返回类型不同,您可以计算 retval 表达式并将其存储在宏第一级内正确类型的变量中,然后使用该变量。即:
如果我理解得很好,这对于您的用例来说应该足够了,对于其他用例,您可以使用函数。
在您的示例中,您会得到:
看起来不错。
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:
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:
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 thewhile(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).我建议您先评估一下病情。
即
除此之外,可能的建议是避免使用宏,在这种情况下它们似乎没有必要,而是使用函数。
I would recommend that you evaluate the condition first.
i.e.
Other than that may advice would be to steer well clear of macros, they seem unnecessary in this instance, use functions instead.
编写函数而不是使用宏。在这种情况下,如果您想要构建一个
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.将宏更改为“静态内联”函数。在 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