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); \ 

使用相同类型的ab创建两个变量,以避免两次评估

更多信息

内联函数最明显的候选者是预处理器宏。 GCC中的内联函数和宏一样可以执行,另外还可以接收类型检查。 例如,而不是这个宏:

 #define max(a,b) ({ a > b ? a : b; }) 

一个人可能会使用相应的内联函数:

 static inline max (int a, int b) { if (a > b) return a; return b; }