VS2013中一个语句中多个指针增量的解决方法

时间:2014-08-29 08:15:20

标签: c

我有一些最近被“移植”到VS的代码。接下来是语句和汇编程序生成,希望“错误”是显而易见的。当然它生成这段代码的方式可能是VS的一个特性,但我不能说我以前见过这个。

switchcount = (int) (*d++) + (*d++<<8) + (*d++<<16) + (*d++<<24);

00A722F6  mov         eax,dword ptr [d]  
00A722F9  movzx       ecx,byte ptr [eax]  
00A722FC  mov         edx,dword ptr [d]  
00A722FF  movzx       eax,byte ptr [edx]  
00A72302  shl         eax,8  
00A72305  add         ecx,eax  
00A72307  mov         edx,dword ptr [d]  
00A7230A  movzx       eax,byte ptr [edx]  
00A7230D  shl         eax,10h  
00A72310  add         ecx,eax  
00A72312  mov         edx,dword ptr [d]  
00A72315  movzx       eax,byte ptr [edx]  
00A72318  shl         eax,18h  
00A7231B  add         ecx,eax  
00A7231D  mov         dword ptr ds:[0AD8CA8h],ecx  
00A72323  mov         ecx,dword ptr [d]  
00A72326  add         ecx,1  
00A72329  mov         dword ptr [d],ecx  

因此编译器生成的代码基本上是

switchcount = (int) (*d) + (*d<<8) + (*d<<16) + (*d<<24);
d += 4 ;

有人能告诉我如何说服编译器生成正确的代码吗?

2 个答案:

答案 0 :(得分:3)

C不允许在序列点之间多次修改同一个变量,并且编译器可以随意处理它 - 就C标准而言,生成代码完全没问题,但是更多有用的行为是中止编译,或至少发出像clang那样的警告:

warning: multiple unsequenced modifications to 'd' [-Wunsequenced]

编写代码的正确方法是

switchcount = (int) (d[0]) + (d[1]<<8) + (d[2]<<16) + (d[3]<<24);
d += 4;

作为旁注,由于整数提升,转换为int是不必要的,但如果您希望C新手读取代码,则可以将其保留为清晰。

根据d的输入值,您将强制转换替换为int并使用强制转换为unsigned - 否则,如果d[3] }至少是128,你的最后一个术语会将值位移到符号位,这又是“未定义的行为”。 (但如果整数由两个补码表示,通常按预期工作。)

答案 1 :(得分:0)

在一个语句中用于处理子表达式的行为(如d ++ mutliple次)是未定义的。您现在面临着不同编译器对语句的不同解释方式 - 避免以这种方式使用表达式。

请参阅Pre & post increment operator behavior in C, C++, Java, & C#