题目
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语法有错,编译阶段就不能通过。