编译warning,字节对齐?奇怪的问题

 看看下面代码的输出是什么:

test.c
  1. #include <stdio.h>
  2. short gs1, gs2, gs3, gs4;
  3. //short gs[4];
  4. int main()
  5. {
  6.         short ls1, ls2, ls3, ls4;
  7.         char in[] = "111:222:333:444";
  8.         sscanf(in, "%d:%d:%d:%d", &gs1, &gs2, &gs3, &gs4);
  9.         sscanf(in, "%d:%d:%d:%d", &ls1, &ls2, &ls3, &ls4);
  10.         printf("glocal %3d:%3d:%3d:%3d/n", gs1, gs2, gs3, gs4);
  11.         printf("local  %3d:%3d:%3d:%3d/n", ls1, ls2, ls3, ls4);
  12. /*
  13.         printf("=========================/n");
  14.         short ls[4];
  15.         sscanf(in, "%d:%d:%d:%d", &gs[0], &gs[1], &gs[2], &gs[3]);
  16.         sscanf(in, "%d:%d:%d:%d", &ls[0], &ls[1], &ls[2], &ls[3]);
  17.         printf("glocal %3d:%3d:%3d:%3d/n", gs[0], gs[1], gs[2], gs[3]);
  18.         printf("local  %3d:%3d:%3d:%3d/n", ls[0], ls[1], ls[2], ls[3]);
  19.         printf("sizeof(short ls[4]) == %d/n", sizeof(ls));
  20. */
  21.         return 0;
  22. }


看下测试结果:
$ 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用什么?



你可能感兴趣的:(优化,汇编,gcc,测试)