面试题答案
一键面试可能出现的问题及不同编译器结果
- 问题:宏
INC(x)
在表达式INC(a) + INC(a)
中会导致未定义行为。因为宏只是简单的文本替换,替换后为int b = ++a + ++a;
,在同一表达式中多次对a
进行自增操作,且自增操作与取值操作顺序不明确,这属于未定义行为。 - 不同编译器结果:
- 某些编译器:可能会按照从左到右的顺序计算,先执行第一个
++a
,a
变为6,再执行第二个++a
,a
变为7,最后b = 7 + 7 = 14
。 - 另一些编译器:可能会以不同顺序计算,例如先计算第二个
++a
,a
变为6,再计算第一个++a
,a
变为7,最后b = 7 + 7 = 14
。但也有可能编译器会进行优化,采用其他计算顺序,得到不同的结果。
- 某些编译器:可能会按照从左到右的顺序计算,先执行第一个
修改宏定义使其行为更可预测
-
方法一:使用函数替代宏
int inc(int x) { return ++x; }
然后在代码中使用
int b = inc(a)+inc(a);
,这样通过函数调用,每次调用inc
函数时,参数求值和函数执行顺序明确,不会出现未定义行为。 -
方法二:如果仍然希望使用宏,可以通过引入临时变量来明确计算顺序
#define INC(x) ({ int temp = x; ++temp; temp; })
这里使用了GCC扩展语法(
({...})
),先将x
的值赋给临时变量temp
,对temp
自增并返回temp
的值。这样在int b = INC(a) + INC(a);
中,每个INC(a)
都有明确的计算顺序,避免了未定义行为。注意,如果不使用GCC扩展语法,也可以通过更为复杂的宏定义来实现类似功能,但这种方法相对简洁。