【发布时间】:2013-12-18 15:17:31
【问题描述】:
min 函数的经典预处理器版本看起来像
#define min(a, b) ((a) < (b) ? (a) : (b))
这会让你面临双重评估——在这种情况下你执行min(f(), g()),忘记了f 或g 有副作用,并且你必须花费数小时试图弄清楚为什么你的函数运行两次.为了防止这种情况,你可以这样做
#define min(a, b) ({__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b;})
这在 GCC 下效果很好,但是如果你通过 Clang 运行它并设置 -Wgnu ——这组警告属于 -pedantic 的保护伞——你会得到类似的错误
test.c:5:10: error: use of GNU statement expression extension [-Werror,-Wgnu]
int a = min(3, 7);
^
test.c:1:22: note: expanded from macro 'min'
# define min(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a < _b ? _a : _b;})
是否可以定义这些宏以防止双重评估和,这在-pedantic 下是 Clang 可以接受的? (是的,您可以使用-Wno-gnu 禁用警告,在这种情况下,Clang 可以毫无问题地处理语句表达式。我之所以这么问是因为我和clang -pedantic 一样,对我自己太挑剔了。)
编辑:我正在使用 C。我也标记了这个 C++,因为我认为一个解决方案可能适用于 C++ 以及 C。糟糕——忘记了模板!很抱歉有歧义。
【问题讨论】:
-
我很好奇为什么 C 和 C++ 标签都是你的目标语言?答案因语言而异。
-
不要使用预处理器,期间。内联函数以更明显的方式更好地完成工作。而且我认为在 C++ 中你甚至可以使用模板来避免为不同类型创建多个函数。
-
为什么这个问题可以接受 C++ 答案,并且明确声明需要 C 并且存在 C 版本?
-
@bdesham,我不明白,该链接并没有增加您在问题中已有的内容。请您详细说明,为什么 C 的答案不太令人满意?现在看来,这是对 C 问题的 C++ 答案,因此它不会为许多其他问题提供帮助。
-
@bdesham 这是样板文件,您只需编写一次。