我已经在C中编程了很长一段时间。所以我决定学习一些关于gcc编译器扩展的高级CI。我看到了MAX()的代码,我现在实现如下< / p>
#define MAX(x,y) ((x) > (y)? (x): (y))
这是我发现的新定义。遗憾的是,我甚至无法理解以下代码的作用?为什么我会这样做,而不是如上所述?
#define MAX(a,b) \
({ \
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
答案 0 :(得分:7)
优点是它避免了像经典宏一样多次评估参数。
通过引入局部变量(使用typeof
来“克隆”参数的类型),实际表达式只被评估一次,返回值则只是使用局部变量而不是再次评估输入表达式,正如经典的宏必须做的那样。
比较如果这样调用会发生什么:
int a = 0, b = 1;
const int c = MAX(++a, ++b);
在第一种情况下,由于输入表达式具有副作用,因此结果难以预测。在第二种情况下,参数仅被评估一次,因此所有内容都表现为MAX()
是常规函数。
另外,你的第一个宏示例是无法将参数括在括号中,这很危险。
答案 1 :(得分:2)
这是一个通用宏的例子,它可以处理不同的数据类型,例如: 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));
因为参数只被评估一次。
答案 2 :(得分:2)
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;
}