一个高中室友最近在准备计算机二级,一直在刷题库的题目(非计算机专业),所以最近一直会问我一些题目,今天他问了我一个问题,关于宏定义的,想起来之前初学C语言的时候,这个问题也是一个典例了,所以决定用博客记录一下。
题目如下:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;int main()
{
int x = 6, y = 4, z = 3, s = 0;
if(x<y) SWAT(s,x,y);
if(x<z) SWAT(s,x,z);
if(y<z) SWAT(s,y,z);
printf("%d %d %d \n", x, y, z);
return 0;
}
执行后的输出结果:A. 6 4 3
B. 3 4 6
C. 0 3 4
D. 3 0 0
思考:
如果我们习惯性思维把宏函数SWAT(t,a,b) 当做平时我们用的普通函数:
x = 6; y = 4; z = 3;
OK 那么 x < y , x < z, y < z;三个式子均不成立
那SWAT()函数不执行,那么x,y,z不变,输出 6 4 3
那我们就跑偏了,答案错误!!
if(x<y) SWAT(s,x,y);
if(x<z) SWAT(s,x,z);
if(y<z) SWAT(s,y,z);
仔细了解过宏定义的概念我们应该知道,宏定义只在预处理时做字符串的简单替换。所以程序清晰的过程是:
替换前:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;
int main()
{
int x = 6, y = 4, z = 3, s = 0;
if(x<y) SWAT(s,x,y);
if(x<z) SWAT(s,x,z);
if(y<z) SWAT(s,y,z);
printf("%d %d %d \n", x, y, z);
return 0;
}
替换后:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;
int main()
{
int x = 6, y = 4, z = 3, s = 0;
if(x<y) s=x;x=y;y=s;
if(x<z) s=x;x=z;z=s;
if(y<z) s=y;y=z;z=s;
printf("%d %d %d \n", x, y, z);
return 0;
}
我们可以看到,虽然三个条件都没有满足,但是判断后面还有两条语句会被执行,我们把中间的变化都输出一下:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;
int main()
{
int x = 6, y = 4, z = 3, s = 0;
// 这里把 y 赋值给了x s赋值给了y
if(x<y) s=x;x=y;y=s;
printf("%d %d %d \n", x, y, z);
// 这里把 z 赋值给了x s赋值给了z
if(x<z) s=x;x=z;z=s;
printf("%d %d %d \n", x, y, z);
// 这里把 z 赋值给了y s赋值给了z
if(y<z) s=y;y=z;z=s;
printf("%d %d %d \n", x, y, z);
printf("end: %d %d %d \n\n", x, y, z);
return 0;
}
结果:
如果我们将SWAT()都放在判断语句中,结果就是 6 4 3 了:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;
int main()
{
int x = 6, y = 4, z = 3, s = 0;
if(x<y) {
SWAT(s,x,y)
};
if(x<z) {
SWAT(s,x,z);
}
if(y<z) {
SWAT(s,y,z);
}
printf("%d %d %d \n", x, y, z);
return 0;
}
预处理后:
#include<stdio.h>
#define SWAT(t,a,b) t=a;a=b;b=t;
int main()
{
int x = 6, y = 4, z = 3, s = 0;
if(x<y) {
s=x;x=y;y=s;
};
if(x<z) {
s=x;x=z;z=s;
}
if(y<z) {
s=y;y=z;z=s;
}
printf("%d %d %d \n", x, y, z);
return 0;
}