三个典型题:
1.
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i)+(++i)+(++i);
printf("ret = %d\n", ret);
return 0;
}
这个代码的运行结果取决于编译器,不同的编译器会有不同的结果,在我们写代码的过程中最好不要写出上似的代码。表达式(++i)+(++i)+(++i),只有操作符的优先级和结合性,没法确定唯一计算路径:
(1)若在gcc编译器下就是这样的规则,按照先1后2相加之后再3的话就是:3+3+4=10,,可能有人会问为啥不是2+3+4=9呢?
进行调试观察汇编代码你会发现(++i)+(++i)+(++i), 中存在多个对同一个变量 i
的自增操作,会对当前状态下的++i进行操作完成后分别赋值给1和2之后,1和2就变了3,进行求和之后对最后一个++i进行和运算,第三个++i就变成了4,所以说在gcc编译器下是10。
(2)若在VS环境下测试,是先对三次++i进行操作完毕之后,分别赋值给1,2,3也就是4+4+4=12。
2.
#include <stdio.h>
int i;
int main()
{
i--;
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
观察这个代码:
在C语言中,全局变量如果没有显式初始化,其初始值为0。因此,对于全局变量int i,其初始值为0。经过i--之后为-1,而 if (i > sizeof(i))判别就要注意了,sizeof(i)的返回值是无符号的整形(unsigned int),对于一个整形内存为4个字节,故此处sizeof(i)的返回值为4,那么通常可能是这样比较 (i > sizeof(i))也就是-1>4不成立,最后程序输出“<”。
但是,需要注意的是,i是有符号的变量i--之后值为-1,当有符号的i与 sizeof()进行运算的时候,会把有符号的i提升为无符号。那么-1提升为无符号,那么-1的补码是11111111111111111111111111111111,是一个很大的数比4肯定大, 比较是用补码进行比较,所以此程序运行结果为“>”。
3.
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5};
short *p = (short*)arr;
int i = 0;
for(i=0; i<4; i++)
{
*(p+i) = 0;
}
for(i=0; i<5; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
观察这个代码:
这个代码short *p = (short*)arr; int类型的arr指针变量被强制转化为short类型的指针变量,于是这个地址p把arr指向short类型的数据。它的1个整形就占两个字节。对于*(p+i) = 0;如i=0,*p= 0,会对当前的两个字节复制为0,并且指针变量解引用的时候每加1就会跳过两个字节。所以最后的输出值为00345