2014-08-29 68 views
2

我有一些代码最近被移植到VS.接下来是声明和汇编器生成的,希望'错误'是显而易见的。当然,它生成这个代码的方式可能是VS的一个特性,但我不能说我以前见过这个。在VS2013中的一个语句中多指针增量的解决方法

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 ; 

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

回答

3

C不允许在顺序点之间多次修改相同的变量,编译器可以自由地以任何方式处理它 - 生成它所做的代码就C标准而言完全没问题,但是更多有用的行为将中止编译,或者至少发出一个警告像铿锵的作用:

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输入值,你应该与强制转换为unsigned更换投地int - 否则,如果d[3]至少是128,你的最后期限将价值位移位至符号位,这是再次'未定义的行为'(但通常按预期工作,如果整数由二进制补码表示)。

+0

非常感谢您提供清晰简洁的答案。 很遗憾,这些语言的设计师在工作时并不记得小学BODMAS/BOMDAS。方括号应确保增量在左括号上从左到右发生。 – mvandere 2014-08-29 21:38:40

0

C语言中用于处理像d ++多重时间之类的子表达式的行为是未定义的。您现在正面临不同编译器对不同编译器的解释方式 - 避免以这种方式使用表达式。

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

+0

同样,虽然这个例子对于大多数编译器是正确的,但简单的()不会改变它的行为。 – mvandere 2014-08-29 21:42:48