最近在项目中遇到了一个奇怪的问题,在此作个标记,以免再犯!!
代码如下:
#include
<
stdio.h
>
int main( int argc, char * argv[])
... {
int c = 9;
c = c++ % 5;
printf("c = %d ", c);
return 0;
}
int main( int argc, char * argv[])
... {
int c = 9;
c = c++ % 5;
printf("c = %d ", c);
return 0;
}
编译器: sparc-elf-gcc 3.2.3
程序执行结果:c = 10 <从正常的分析来看,结果应该是5>
为什么呢?是不是sparc的编译器对c=c++%5做了其它的理解呢?因此把这段代码反编译得出其汇编代码如下:
编译命令:sparc-elf-gcc -g -o test.exe test.c
sparc-elf-objdump -D test.exe > dump.txt
40001174
<
main
>
:
40001174 : 9d e3 bf 90 save % sp, - 112 , % sp
40001178 : f0 27 a0 44 st % i0, [ % fp + 0x44 ]
4000117c: f2 27 a0 48 st % i1, [ % fp + 0x48 ]
40001180 : 90 10 20 09 mov 9 , % o0
40001184 : d0 27 bf f4 st % o0, [ % fp + - 12 ]
40001188 : c0 27 bf f0 clr [ % fp + - 16 ]
4000118c: a2 07 bf f4 add % fp, - 12 , % l1
40001190 : e0 04 40 00 ld [ % l1 ], % l0
40001194: 90 10 00 10 mov %l0, % o0
40001198 : 92 10 20 05 mov 5 , % o1
4000119c: 40 00 00 13 call 400011e8 < .rem >
400011a0: 01 00 00 00 nop
400011a4: d0 27 bf f4 st %o0, [ %fp + -12 ]
400011a8: a0 04 20 01 inc % l0
400011ac: e0 24 40 00 st %l0, [ % l1 ]
400011b0: d0 07 bf f4 ld [ % fp + - 12 ], % o0
400011b4: d0 27 bf f0 st % o0, [ % fp + - 16 ]
400011b8: 11 10 00 26 sethi % hi( 0x40009800 ), % o0
400011bc: 90 12 20 00 mov % o0, % o0 ! 40009800 < ___DTOR_END__ >
400011c0: d2 07 bf f0 ld [ % fp + - 16 ], % o1
400011c4: 40 00 00 c7 call 400014e0 < printf >
400011c8: 01 00 00 00 nop
400011cc: 90 10 20 00 clr % o0 ! 0 <* ABS *>
400011d0: b0 10 00 08 mov % o0, % i0
400011d4: 01 00 00 00 nop
400011d8: 81 c7 e0 08 ret
400011dc: 81 e8 00 00 restore
40001174 : 9d e3 bf 90 save % sp, - 112 , % sp
40001178 : f0 27 a0 44 st % i0, [ % fp + 0x44 ]
4000117c: f2 27 a0 48 st % i1, [ % fp + 0x48 ]
40001180 : 90 10 20 09 mov 9 , % o0
40001184 : d0 27 bf f4 st % o0, [ % fp + - 12 ]
40001188 : c0 27 bf f0 clr [ % fp + - 16 ]
4000118c: a2 07 bf f4 add % fp, - 12 , % l1
40001190 : e0 04 40 00 ld [ % l1 ], % l0
40001194: 90 10 00 10 mov %l0, % o0
40001198 : 92 10 20 05 mov 5 , % o1
4000119c: 40 00 00 13 call 400011e8 < .rem >
400011a0: 01 00 00 00 nop
400011a4: d0 27 bf f4 st %o0, [ %fp + -12 ]
400011a8: a0 04 20 01 inc % l0
400011ac: e0 24 40 00 st %l0, [ % l1 ]
400011b0: d0 07 bf f4 ld [ % fp + - 12 ], % o0
400011b4: d0 27 bf f0 st % o0, [ % fp + - 16 ]
400011b8: 11 10 00 26 sethi % hi( 0x40009800 ), % o0
400011bc: 90 12 20 00 mov % o0, % o0 ! 40009800 < ___DTOR_END__ >
400011c0: d2 07 bf f0 ld [ % fp + - 16 ], % o1
400011c4: 40 00 00 c7 call 400014e0 < printf >
400011c8: 01 00 00 00 nop
400011cc: 90 10 20 00 clr % o0 ! 0 <* ABS *>
400011d0: b0 10 00 08 mov % o0, % i0
400011d4: 01 00 00 00 nop
400011d8: 81 c7 e0 08 ret
400011dc: 81 e8 00 00 restore
果然发现了猫腻,sparc-elf-gcc编译器把c的初值(=9)拷贝了两份,分别放在o0和l0中,用o0做了(9%5)的操作,并将值写回到了栈中,然后又用l0中原来存放的值(=9)做自增操作,其结果等于10,并写回到原来的单元中,这样就覆盖了上次的值,所以输出为10。
结果分析:sparc-elf-gcc可能为了节省数据读取的时间,将初值拷贝了两份,导致后用的值没有和sram中同步,这可能是sparc-elf-gcc的一个bug!同样的,这样的程序风格也不值得提倡!~引以为戒
延伸:我用标准gcc或者vc6.0自带的c编译器进行编译的时候是没有问题的!