c - 在 C 中,*、=、++、<< |运算符(operator)

标签 c operator-keyword operator-precedence

u8 num[] = {0x00, 0x00, 0x40};

u8*ptr = num;

u8 tag;

u16 len;

tag = *ptr++;

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

我期望 len = 0x0040 但 len 在 vi​​sual studio 2013 中设置为 0x0000。 我不知道为什么会这样。 你能从运算符优先的角度解释一下吗?

最佳答案

关于运算符优先级,我建议你先看看这个table .

现在,++/--可能是棘手的运算符,因为您需要确定它们是前缀运算符还是后缀运算符,正如您在表中看到的那样,如果它们是前缀运算符,它们的优先级与 * 相同(取消引用)。

那么,让我们分析一下最后一行 len = (u16)*ptr++ <<8 | *ptr++; 发生了什么, 有这组运算符 {=, (cast), *(dereference), ++(postfix), <<, |} , 所以评价顺序按照这个table将是 ++(postfix), *dereference, (type), <<, |, =

这与评估顺序有关,但您需要考虑:

Postfix increment/decrement have high precedence, but the actual increment or decrement of the operand is delayed (to be accomplished sometime before the statement completes execution).

也就是说,这里有几种方法可以实现您想要的:

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

或:

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

最后一个建议,当你处理具有相同优先级的运算符时要小心,正如你在表中看到的,结合性可以是从左到右或从右到左。

PS: 当然,生成的 asm 代码将取决于所使用的编译器和配置,这是该行在 Debug模式下的 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

快乐编码。

关于c - 在 C 中,*、=、++、<< |运算符(operator),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44161078/

相关文章:

C语言中字符串转长时间

c++ - & 符号 '&' 参数末尾的运算符

Java 复杂运算符优先级(后缀、一元、关系、逻辑 AND、赋值)

c++ - 运算符的不明确重载

c++ - 按指定的顺序迭代元组的元素

c++ - 是否必须使逻辑运算符短路?和评估顺序?

c++ - 连接到网络的所有设备的列表

c - 如何使用带有 CTest 的检查库在 C 中进行单元测试

c - 试图不覆盖 C 中的文件?

java - 运算符>>和<<在处理中的含义