看看下面代码的输出是什么:
test.c
- #include <stdio.h>
- short gs1, gs2, gs3, gs4;
- int main()
- {
- short ls1, ls2, ls3, ls4;
- char in[] = "111:222:333:444";
- sscanf(in, "%d:%d:%d:%d", &gs1, &gs2, &gs3, &gs4);
- sscanf(in, "%d:%d:%d:%d", &ls1, &ls2, &ls3, &ls4);
- printf("glocal %3d:%3d:%3d:%3d/n", gs1, gs2, gs3, gs4);
- printf("local %3d:%3d:%3d:%3d/n", ls1, ls2, ls3, ls4);
- return 0;
- }
看下测试结果:
$ gcc -Wall test.c ;./a.out
glocal 0:222: 0:444
local 0: 0: 0:444
$ gcc -Wall test.c -O2;./a.out
glocal 0:222: 0:444
local 111:222:333:444
$ g++ -Wall test.c ;./a.out
glocal 111:222:333:444
local 0: 0: 0:444
$ g++ -Wall test.c -O2;./a.out
glocal 0: 0: 0:444
local 111:222:333:444
可能反汇编能看出端倪,可惜汇编我不熟悉,但通过这次测试,我想说明以下几点:
1. 输出不正确的原因:
%d是输入int,4个字节,接收变量确实占两个字节的short,所以覆盖临近的2个字节
有输出和期望相同的,有两种可能:
1)变量虽然只用了2个字节,分配了4个字节,即多分配了2个字节
2)有些输出正确,可能是字节对齐的关系,没有联系分配地址,避免被覆盖
3)另一种可能处理顺序不同,一种顺序会覆盖未赋值的内存(表现为正常),另一种会覆盖已赋值的内存(表现为被覆盖)
+--+---+---+---+---+
111 000
222 000
333 000
444 000
------值正常------> 按这个顺序,覆盖的是不需要的部分
<-----值被覆盖----- 按这个顺序,覆盖的是需要的部分
看汇编应该能看出来是什么原因,可惜我不会,我猜想第二种可能性比较大,也就是字节对齐的关系
2. gcc和g++,优化和不优化,堆和栈分配,结果可能不同。(废话??!)
3. 把注释掉的代码打开,会发现结果还会不一样,高人tell me why吧?
4. 我不知道真正的原因是什么,我知道以后要更小心地处理warning
编译的时候会报 warning: int format, different type arg (arg 3)
以前经常都忽略warning的,现在看来warning比error更麻烦,因为warning可能会导致运行出错
ps: 我只知道可以用%ld输入long long int, 谁知道输入short用什么?