【问题标题】:in C, *, =, ++, << | operator在 C 语言中,*、=、++、<< |操作员
【发布时间】:2017-10-24 22:58:26
【问题描述】:
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。 我不知道为什么会这样。 你能用运算符优先级的观点来解释吗?

【问题讨论】:

  • 添加一些括号,您将不需要依赖运算符优先级。问题解决了。 (尽管 ++ 可能存在未定义的行为)
  • 答案很简单:不要这样写代码。用括号写,或者单独的行,然后让编译器优化它。
  • 当我在 HP-UX 下编译您的代码时,它会按您的预期运行。这归结为“实现定义的行为”,特别是“何时调用 ++ 运算符?”。 VS 显然直到语句完成后才增加指针,这是合理的,因为语句中间没有序列点。相反,HP-UX C 编译器在每次访问后立即递增指针(显然 - 我没有反汇编代码来检查),这是允许但不是必需的。
  • 如果你写的代码在写的时候很难看懂,最好换一种风格试试。想想几个月后做维护的可怜人(这可能是你)
  • 最后一行是未定义的行为(ptr 写了两次没有序列点)

标签: c operator-keyword operator-precedence


【解决方案1】:

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

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

所以,让我们分析一下你的最后一行 len = (u16)*ptr++ &lt;&lt;8 | *ptr++; 的情况,有这组运算符 {=, (cast), *(dereference), ++(postfix), &lt;&lt;, |},所以根据这个 table 的评估顺序将是 ++(postfix), *dereference, (type), &lt;&lt;, |, =

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

后缀递增/递减具有高优先级,但 操作数的实际递增或递减被延迟(要 在语句完成执行之前的某个时间完成)。

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

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

或:

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

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

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

编码愉快。

【讨论】:

  • ++ 的副作用没有排序,并且操作数可能会比您在列表中给出的更早进行评估
  • @M.M Op 说他正在使用 Visual Studio 2013,我已经测试过并且我已经提到了那个编译器,你能详细说明你的意思吗?
  • 不存在您声称的排序(在标准 c++ 中)。您在 vc++ 的特定运行中观察到的行为可能会或可能不会在其他运行中复制,即使使用相同的编译器
  • @M.M 编辑了答案...您能否提供支持您评论的 c/c++ 标准的链接/参考?添加它以提供有关该主题的更多相关信息会很酷
猜你喜欢
  • 2014-09-30
  • 2011-08-08
  • 2010-10-03
  • 2012-03-30
  • 2023-04-04
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多