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



我有一些代码最近被"移植"到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 ;

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

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,则最后一项将把值位移到符号位,这也是"未定义行为"(但如果整数由2的补码表示,则正常工作)。

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

请参阅Pre&C、C++、Java和&C#

相关内容

最新更新