2017-05-24 183 views
1
u8 num[] = {0x00, 0x00, 0x40}; 

u8*ptr = num; 

u8 tag; 

u16 len; 

tag = *ptr++; 

len = (u16)*ptr++ <<8 | *ptr++; 

我希望len = 0x0040但LEN在Visual Studio 2013年 设置好的与0x0000我不知道这是为什么发生。 你会用运算符优先级来解释吗?运营商

+2

添加一些括号,您将不需要依赖运算符优先级。问题解决了。 (尽管用++可能会有未定义的行为) – byxor

+2

答案很简单:不要编写那样的代码。用圆括号或单独的行编写它,然后让编译器优化它。 –

+0

[为什么这些构造(使用++)未定义的行为?](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) –

回答

1

关于运营商的优先权,我建议你先看看这个table

现在,++/--可能会非常棘手,因为运营商需要确定他们是否是前缀或后缀运算符,你可以在表中看到,如果他们前缀的人,他们会具有相同的优先级比*(解引用) 。

那么,让我们analize做什么用你的最后一行len = (u16)*ptr++ <<8 | *ptr++;去,有这一套运营商{=, (cast), *(dereference), ++(postfix), <<, |}的,所以根据这个table评价的顺序将是++(postfix), *dereference, (type), <<, |, =

这会是关于以评估顺序,但你需要考虑:

后缀递增/递减具有高优先级,但操作数的 实际增量或减量延迟(以 某个时候完成的语句完成EXECUT前离子)。

这就是说,这里的一对夫妇的方式来实现你想要什么:

ptr[1]<<8 | ptr[2] 

或:

*(ptr+1) <<8 | *(ptr+2) 

最后一个建议,要小心,当你处理与运营商正如您在表格中看到的,相同的优先级可以是从左到右或从右到左。

PS:当然,生成将取决于所使用的编译器&配置的汇编代码,这里是在该行的调试模式vs2015的例子:

; 7 :  u16 len = (u16)*ptr++ <<8 | *ptr++; 

    mov ecx, DWORD PTR _ptr$[ebp] 
    movzx edx, BYTE PTR [ecx] 
    shl edx, 8 
    mov eax, DWORD PTR _ptr$[ebp] 
    movzx ecx, BYTE PTR [eax] 
    or edx, ecx 
    mov WORD PTR _len$[ebp], dx 
    mov edx, DWORD PTR _ptr$[ebp] 
    add edx, 1 
    mov DWORD PTR _ptr$[ebp], edx 
    mov eax, DWORD PTR _ptr$[ebp] 
    add eax, 1 
    mov DWORD PTR _ptr$[ebp], eax 

编码愉快。

+0

'++'的副作用没有排序,并且操作数可能比您在列表中给出的时间早 –

+0

@MM Op说他正在使用visual studio 2013,我已经测试过并且已经提到了该编译器,你能详细说明你的意思吗? – BPL

+1

不存在您声明的顺序(在标准C++中)。在特定运行的vC++上观察到的行为可能会或可能不会在其他运行中被复制,即使使用相同的编译器 –