C语言宏中表达式与语句的异常行为及原因解析
C语言宏定义引发的三个输出异常解析
场景1:输出5 3的原因
#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; if ((3+big(a,b)>b)){ swap(a,b); } printf("%d %d",a,b); return 0; }
宏是纯文本替换,没有函数的参数括号保护。big(a,b)替换后直接是a>b?a:b,所以3+big(a,b)>b会被展开成:
3 + a > b ? a : b > b
C语言运算符优先级:+ > > > ?:,计算顺序为:
- 先算
3+a,a=3,结果为6 - 再算
6>b(b=5),结果为真(非0) - 三元表达式取
a的值3,整个条件表达式最终值为3(非0),if条件成立,执行swap(a,b)交换a和b,输出5 3。
场景2:加括号后输出3 5的原因
#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; if ((3+big(a,b))>b){ swap(a,b); } printf("%d %d",a,b); return 0; }
这次条件(3+big(a,b))>b展开后是:
(3 + a > b ? a : b) > b
计算顺序为:
- 先处理括号内的
3+a>b?a:b:3+a=6,6>5为真,取a=3,括号内结果是3 - 再算
3>b(b=5),结果为假(0),if条件不成立,不执行交换,输出3 5。
本质是宏没有自带括号,导致3+big(a,b)的实际运算逻辑和预期不符——你以为是3+(a和b的较大值),但实际是(3+a)和b比较后取a或b。
场景3:去掉花括号后输出5 0的原因
#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; if ((3+big(a,b))>b) swap(a,b); printf("%d %d",a,b); return 0; }
swap(a,b)宏展开后是三条独立语句:temp=a; a=b; b=temp;。而C语言中,if后面没有花括号时,只执行紧跟的第一条语句,代码展开后等价于:
if ((3+big(a,b))>b) temp=a; a=b; b=temp;
和场景2一样,if条件为假,不执行temp=a;。但后面的a=b;和b=temp;是独立于if的无条件执行语句:
a=b:a被赋值为5b=temp:temp是未初始化的局部变量,栈上默认值通常为0(或随机值,此处恰好为0),b被赋值为0
最终输出5 0。
内容的提问来源于stack exchange,提问作者Amogh GC
相关产品推荐
相关产品推荐

