MAX使用gcc的typeof扩展名
我已经用C语言编程了很长一段时间。所以我决定学习一些关于gcc编译器扩展的高级CI。我看到了MAX()的代码,我现在已经实现如下
#define MAX(x,y) ((x) > (y)? (x): (y))
这是我发现的新定义。遗憾的是,我甚至无法理解下面的代码是做什么的? 为什么我会这样做,而不是如上所述?
#define MAX(a,b) \ ({ \ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a > _b ? _a : _b; })
优点是它避免了像经典宏一样多次评估参数。
通过引入局部变量(使用typeof
来“克隆”参数的类型),实际表达式只被计算一次,然后返回值只是使用局部变量而不是再次评估输入表达式,因为经典宏必须做。
比较如果这样调用会发生什么:
int a = 0, b = 1; const int c = MAX(++a, ++b);
在第一种情况下,因为输入表达式具有副作用,所以结果将难以预测。 在第二种情况下,参数仅被评估一次,因此一切行为就像MAX()
是常规函数一样。
此外,您的第一个宏示例是无法将参数括在括号中的任何地方,这很危险。
这是一个通用宏的示例,它将使用不同的数据类型,例如int或float。 例如:
int i = 10; int j = 20; int k = MAX(i, j);
扩展为:
int i = 10; int j = 20; int k = ({ int _a = (i); int _b = (j); _a > _b ? _a : _b; });
然而:
float x = 10.0f; float y = 20.0f; float z = MAX(x, y);
扩展为:
float x = 10.0f; float y = 20.0f; float z = ({ float _a = (x); float _b = (y); _a > _b ? _a : _b; });
它甚至可以用于混合数据类型,例如
int i = 10; float y = 20.0f; float z = MAX(i, y);
除了支持不同的数据类型,它还避免了更简单的宏的令人讨厌的副作用,例如
#define MAX(a, b) (((a) > (b)) ? (a) : (b)))
如果你调用它,它会表现得不合需要
int k = MAX(i++, j++);
此外,如果将表达式作为参数传递,则效率会更高,例如
float x = 10.0f; float y = 20.0f; float z = MAX(sin(x), sin(y));
因为参数只被评估一次。
typeof (a) _a = (a); \ typeof (b) _b = (b); \
使用相同类型的a
和b
创建两个变量,以避免两次评估
更多信息
内联函数最明显的候选者是预处理器宏。 GCC中的内联函数和宏一样可以执行,另外还可以接收类型检查。 例如,而不是这个宏:
#define max(a,b) ({ a > b ? a : b; })
一个人可能会使用相应的内联函数:
static inline max (int a, int b) { if (a > b) return a; return b; }