题目
1、下面程序的输出结果是多少
-
#include <stdio.h>
-
#define square2(x) ((x)*(x))
-
int square1(int x)
-
{
-
return x*x;
-
}
-
int main(void)
-
{
-
int i = 1, j = 1;
-
i = square1(++i);
-
j = square2(++j);
-
printf("%d %d\n", i, j);
-
return 0;
-
}
2、下面两个程序语法是否错误,如果错了,为什么?如果没有错,输出结果是多少?
-
#include <stdio.h>
-
int main(void)
-
{
-
int i = 1;
-
++i = i+++i;
-
printf("%d\n", i);
-
return 0;
-
}
-
#include <stdio.h>
-
int main(void)
-
{
-
int i = 1;
-
i++ = i+++i;
-
printf("%d\n", i);
-
return 0;
-
}
分析
第一题
square1是求平方的函数,因为先执行了++i
,i的值变为2,然后执行表达式i=square1(i)
,所以i=2*2=4
。
square2也是求平方的函数,但是是通过宏定义实现的。宏定义是简单的字符串替换,所以j = square2(++j)
,展开后的结果是j = ((++j)*(++j))
。等价于:
++j;
++j;
j = j*j;
结果为9
所以第一题答案是4 9
这里通过宏定义实现求平方的函数。
好处是减少了一次函数调用,在编译阶段就直接展开成了表达式,会提高程序执行效率。
缺点在于本题中的现象,容易出现错误,结果偏离了函数调用者的预期。这种情况常被叫做宏定义陷阱,也就是说很容易弄错。
第二题
第二题第一个程序语法是正确的,主要的一句是++i = i+++i
,这句话实际上等效于(++i) = (i++) + i
。根据C语言的语法特点,也就相当于:
++i;
i=i+i;
i++;
所以第一个程序的答案是5
第二个程序和第一个程序只有一点不同,++i = i+++i
被改成了i++ = i+++i
。这个在语法上是有问题的。
在C语言中,i++
是右值,而++i
是左值。所谓右值,就是可以放在一个等号表达式右边的;而左值,既可以放在右边,也可以放在等号左边并对其进行赋值。
所以++i = i+++i
是可以执行的,而i++ = i+++i
语法有错,编译阶段就不能通过。