何时在C中未定义按位运算?

时间:2018-04-16 15:28:43

标签: c language-lawyer bitwise-operators undefined-behavior c99

这个问题是关于C标准需要什么,而不是主流编译器可以可靠地做什么。让我们关注C99,尽管有关C89 / ANSI或C11如何分歧的输入也会受到欢迎。

第6.2.6.2节介绍了整数类型的“负0”的概念,在使用整数的符号和幅度表示的系统中为0x8000...,或者0xFFFF...系统使用一个补码表示。 (该标准还允许此类系统将这些位模式用于陷阱值而不是负0;并且使用显性/更常见的二进制补码表示的系统没有负0。)

在该部分中,标准说:

  
      
  1. 如果实现支持负零,则只能通过以下方式生成:

         
        
    • &|^~<<>>运算符以及产生此类值的参数
    •   
    • ...
    •   
         

    未指明这些情况是否实际产生负零或正常零,以及当存储在对象中时负零是否变为正常零。

  2.   
  3. 如果实施不支持否定零,则&|^~<<和{的行为{1}}具有可生成此类值的参数的运算符未定义。

  4.   

据我所知,该标准没有进一步明确“产生这种价值的论据”的含义。但阅读本文的自然方式表明,任何类似>>的操作,您希望结果实际上符合标准x | y0x8000...具有未定义的行为。

咦?真的吗?所以根据标准,即使在二进制补码机上,0xFFFF...确实会导致未定义的行为?那疯狂。这不是预期的解释。

他们的意思是,或许:在使用符号和幅度或一个补码表示的系统上,具有负零,那么将产生如果那些系统有一个未定义,则为负零的位模式。在具有两个补码表示的系统上,此处的标准保持沉默?

如果你在标准中看得更远(第6.5.7节),它会告诉我们:

~0

(这里我假设输入uint32_t x = 1; int32_t y = 1; x << -1; /* is undefined, so is y << -1 */ x << 32; /* is undefined, so is y << 32 */ y << 31; /* shifting 1 into sign bit is also undefined */ ((int32_t) -1) << 1; /* is undefined */ ((int32_t) -1) >> 1; /* is implementation-defined */ s的小整数文字的排名不高于intint32_t。)

在后面的这些部分中,标准没有说明何时使用uint32_t&|^的操作未定义的具体内容。 (它只是说在操作数上执行“通常的算术转换”。如果转换提升为有符号类型某些超出范围的无符号值,并且我理解转换规则正确,则只会导致未定义的行为,这永远不会发生。)

0 个答案:

没有答案