这些表达式中的任何一个都是未定义行为(UB)吗?

  1. 0 << 32
  2. 0LL << 64

如果答案包含对 C 标准的引用,我将不胜感激。

11

  • 1
    我只是想确定一下。坦率地说,我不会感到惊讶,因为 C 标准有时确实让我感到惊讶。例如,当它指出 1 << 31 是未定义行为时。


    – 

  • 1
    你的意思是0 << (CHAR_BIT * sizeof 0)和吗0LL << (CHAR_BIT * sizeof 0LL)


    – 

  • 3
    @Lundin 实际上你当然是对的。但是这里标记为“语言律师”的帖子不是需要更高级别的“严格性”吗(这也适用于答案)?我实际上避免在这里发布答案,因为我不确定我是否能坚持这种“严格性”。


    – 


  • 2
    @Lundin:当问题被标记为语言律师时,它是关于语言规则的,而不是你声称人们关心的内容。


    – 

  • 2
    @Lundin:当问题被标记为语言律师时,它就与语言规则有关,无论您对问题或答案的价值有何看法。


    – 


最佳答案
1

请参阅,6.5.7按位移位运算符第 3 段

对每个操作数执行整数提升。结果的类型是提升后的左操作数的类型。如果右操作数的值为负数或大于或等于提升后的左操作数的宽度,则行为未定义。

假设32位int和64位的通用配置long long

分析0 << 32表达式:右操作数为整型常量 32,其值等于左操作数的宽度(int)。因此行为未定义。

分析0LL << 64表达式:右操作数是整型常量 64,其值也等于左操作数的宽度(long long)。因此行为也是未定义的。

0 << 32都会0LL << 64导致 C 中的未定义行为 (UB)。

10

  • 1
    @Shelton Liu 您能修改一下您的答案吗?


    – 

  • 1
    这个答案既完全正确又完全错误:这些表达式确实有未定义的行为,但仅仅是因为这个答案引用的段落之前的段落。


    – 

  • 1
    @lollol 编辑后答案现在正确了。在这种情况下,左操作数的值无关紧要,因为右操作数导致了 UB。无论左移还是右移,它都是 UB。


    – 

  • 1
    删除了我之前的评论。他们参考了编辑前的原始答案。


    – 


  • 4
    此答案假设一台机器具有 32 位int对象和 64 位对象。在具有较小和对象long long的机器上,它也是 UB (出于同样的原因)。在具有较大类型的机器上,它不是 UB,但我怀疑是否存在这样的机器。intlong long


    –