c - 以下哪一个宏是安全的,为什么?

标签 c gcc c-preprocessor

为了获得两个数中的最大值,我有以下宏

#define max(a,b) ((a) > (b) ? (a) : (b))

#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })

以上两者有什么区别。哪个更好用,为什么。 我找到了这些宏的信息 here .但无法理解。

最佳答案

第二个宏更安全,但使用了 GCC 提供的非标准 C 扩展:statement expressions .但第一个表达是“通用的”。使用 typeof GCC 的扩展将有助于:

 #define mymax(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); \
                      _a > _b ? _a : _b; })

解决 JaredPar's answer 中提出的问题你可以使用预处理器 concatenation和 GCC 具体 __COUNTER__ (或者只是更标准的 __LINE__),例如

 #define mymax_counted(a,b,c) ({typeof(a) _a##c = (a); \
                                typeof(b) _b##c = (b); \
                                _a##c > _b##c ? _a##c : _b##c; })
 #define mymax(a,b) mymax_counted(a,b,__COUNTER__)

但即使这样也不能完全防止失败(运气不好;如果唯一的 __COUNTER__ 恰好是当时有 123 个)。

实际上,使用 inline function更好(因为如果你调用 mymaxfun(i++,t[i]) 行为定义明确并且给出与 mymaxfun(t[i],i++) 相同的结果,并且因为优化编译器会产生与使用宏时一样高效的代码):

static inline int mymaxfun(int a, int b) { return (a>b)?a:b; }

遗憾的是,C 没有通用函数(考虑切换到 C++ 及其 templates 并使用 std::max );然而C11具有使用 _Generic 关键字的泛型表达式

宏很有用(如果掌握了),但是在调用宏(例如 mymax(i++,t[--i]++))时你应该非常小心参数中的副作用,所以你始终应该注意并记录 名称是宏还是其他名称(如函数)。根据经验,避免副作用 - 特别是 ++-- 以及许多其他 - 在函数调用查找表达式(函数调用和宏调用)中。

查看源代码的预处理器扩展形式;所以对于 foo.c 源代码,运行 gcc -C -E foo.c > foo.i (添加任何预处理器选项,如 -I, -D 等...是相关的)并查看 foo.i 例如使用 less foo.i;它总是有启发性的。

关于c - 以下哪一个宏是安全的,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21300883/

相关文章:

从 printf 调用另一个函数?

c - 服务器不接受来自客户端的连接以从文件读取数据

gcc - 使用编译器选项覆盖宏

c - 使用 SSE 将 4 个 float 乘以 4 个 float 的最有效方法是什么?

c++ - 是否可以在 VSVC 和 GCC 中统一 std::wstring 行为?

C 预处理器宏顺序

c++ - 从 C/C++ 快速检索 lua 对象

c - 如何避免 C 头文件覆盖 native C++ 类型

c++ - 为什么 gcc 在递归扩展宏时中断

c - 使用 printf 时出现意外结果