Lun*_*din 19 c signed bitwise-operators twos-complement language-lawyer
C17 6.2.6.2/4说:
如果实现不支持负零,则未定义&,|,^,〜,<<和>>运算符的行为,其操作数会产生这样的值。
如果我有一个2的补码系统,则它不支持负零。并且它始终利用二进制数的所有可能组合来表示一个值。因此,无论使用哪种按位运算,都不可能产生负零。那么这段文字是什么意思呢?
我认为这部分是指具有1的补码或带符号幅度的系统,该系统不支持负零,而是使用填充位或陷阱表示。它是否正确?
Jen*_*edt 14
是的,我认为您的解释是正确的。在二进制补码中,没有可以产生负零的运算,因为这里的概念不存在:设置了符号位的任何值都必须小于0
。
顺便说一句:很有可能从C2x中删除了外来符号表示,因此所有这些都将消失。
dbu*_*ush 12
您的解释是正确的。
转到6.2.6.2第2段:
对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位。不需要任何填充位;带符号的字符不得有任何填充位。恰好有一个符号位。作为值位的每个位应具有与对应的无符号类型的对象表示形式中的相同位相同的值(如果有符号类型中有M个值位,无符号类型中有N个值位,则M?N)。如果符号位为零,则它将不影响结果值。如果符号位为1,则应通过以下方式之一修改值:
- 取反符号位0的对应值(符号和幅度);
- 符号位是否具有值?(2 M)(二进制补码);
- 符号位是否具有值?(2 M?1)(补码)。
其中哪一个适用于实现定义,即符号位为1且所有值位为零(对于前两个)还是符号位且所有值位为1(对于补码)的值都是陷阱表示或正常值。在符号,大小和“ 1”的补码情况下,如果此表示形式是正常值,则称为负零。
这意味着对于给定的大小整数类型,使用一个人的补码或一个符号和一个量值的实现具有特定的表示,该表示必须为负零或陷阱表示。然后由实现选择哪个选项适用。
举例来说,假设系统具有符号和大小表示形式,并且具有32位int
且没有填充。那么如果支持负零表示,则为0x80000000
。
现在假设执行以下操作:
int x = 0x7fffffff;
x = ~x;
Run Code Online (Sandbox Code Playgroud)
如果实现支持负零,则~
运算符将生成-0
结果并将其存储在中x
。如果没有,它将创建一个陷阱表示并根据第4段调用未定义的行为。