提问人:Kanishk 提问时间:10/27/2023 最后编辑:Vlad from MoscowKanishk 更新时间:10/28/2023 访问量:101
使用带有参数的宏时出现意外结果 [duplicate]
Getting unexpected results when using macros with arguments [duplicate]
问:
#include <stdio.h>
#define big(a, b) a > b ? a : b
#define swap(a, b) temp = a; a = b; b = temp;
int main() {
int a = 3, b = 5, temp = 0;
if ((3 + big(a, b)) > b)
swap(a, b);
printf("%d %d", a, b);
}
上面的代码是在多项选择题中给出的。 我以为答案是 5 3。在运行代码时,输出为 5 0。我试图理解这一点,但我的努力是徒劳的。这段代码的工作原理是什么?
答:
1赞
Vlad from Moscow
10/27/2023
#1
只需展开代码中的宏,即可获得
int main() {
int a = 3, b = 5, temp = 0;
if ((3 + a > b ? a : b ) > b)
temp = a;
a = b;
b = temp;
printf("%d %d", a, b);
}
由于条件运算符中的第一个表达式等于 ,则条件运算符的结果是 的值小于 。3 + a
6
a
b
因此,if 语句的条件计算结果为逻辑 false,并且语句
temp = a;
被跳过。
因此,将等于 并且将等于 。a
5
b
0
您需要使用括号。例如
#define big(a, b) ( ( a ) > ( b ) ? ( a ) : ( b ) )
#define swap(a, b) do { temp = ( a ); ( a ) = ( b ); ( b ) = temp; } while ( 0 )
1赞
Oka
10/27/2023
#2
gcc -E
(仅预处理)呈现以下输出:
int main() {
int a = 3, b = 5, temp = 0;
if ((3 + a > b ? a : b) > b)
temp = a; a = b; b = temp;;
printf("%d %d", a, b);
}
由此我们可以看出,语句的主体仅由第一个表达式语句 () 组成,以第一个分号结尾。if
temp = a;
a = b; b = temp;;
落在身体之外,被无条件执行。还要注意额外的分号。if
在宏中包含多个表达式语句的典型模式是利用 ,它将语句分组到新的块作用域,并允许使用尾部分号以保持一致。do { ... } while (0)
另一件事是积极地将宏参数(通常是整个宏)括起来,以确保运算符优先级尽可能保持一致。
请注意,依赖要定义的隐式变量是一种代码异味。更好的方法的一种可能性是传递类型。swap
temp
#include <stdio.h>
#define big(a, b) (((a) > (b)) ? (a) : (b))
#define swap(type, a, b) do { type temp = (a); (a) = (b); (b) = temp; } while (0)
int main(void)
{
int a = 3, b = 5;
if ((3 + big(a, b)) > b)
swap(int, a, b);
printf("%d %d\n", a, b);
}
预处理器输出:
int main(void)
{
int a = 3, b = 5;
if ((3 + (((a) > (b)) ? (a) : (b))) > b)
do { int temp = (a); (a) = (b); (b) = temp; } while (0);
printf("%d %d\n", a, b);
}
程序输出:
5 3
此示例未解决的一个问题是,这两个宏都不止一次地评估它们的论点,当涉及副作用时,这变得很棘手(例如,)。macro(func(x++), y--)
Смотритетакже: GCC CPP - 3.10.4 副作用的重复
评论
swap