C17 6.2.6.2/4说:
如果实现不支持负零,则使用将产生此类值的操作数的&、|、^、〜、<<和>>运算符的行为是未定义的。
如果我有一个二进制补码系统,它不支持负零。并且始终利用所有可能的二进制数字组合来表示一个值。因此,无论使用哪个位运算符,都不可能产生负零。那么这段文字的意思是什么呢?
我的理解是,该部分涉及到不支持负零的1的补码或有符号幅度系统,而是使用填充位或陷阱表示。这样理解正确吗?
C17 6.2.6.2/4说:
如果实现不支持负零,则使用将产生此类值的操作数的&、|、^、〜、<<和>>运算符的行为是未定义的。
如果我有一个二进制补码系统,它不支持负零。并且始终利用所有可能的二进制数字组合来表示一个值。因此,无论使用哪个位运算符,都不可能产生负零。那么这段文字的意思是什么呢?
我的理解是,该部分涉及到不支持负零的1的补码或有符号幅度系统,而是使用填充位或陷阱表示。这样理解正确吗?
是的,我认为您的理解是正确的。在二进制补码中,不存在可以产生负零的操作,因为这里的概念并不存在:任何带符号位的值必然小于0
。
顺便说一句:很可能奇异的符号表示法将从C2x中删除,所以所有这些都将消失。
你的解释是正确的。
跳到 6.2.6.2 的第二段:
对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;signed char 不得具有任何填充位。必须恰好有一个符号位。每个是值位的位在相应的无符号类型的对象表示中都具有相同的值(如果有 M 个值位,则带符号类型的 N 位无符号类型中有 N ≥ M)。如果符号位为零,则它不会影响结果值。如果符号位为1,则值将以以下方式之一修改:
- 对应的符号位为零的值被取反(符号-大小)
- 符号位的值为 - (2M) (补码)
- 符号位的值为 - (2M - 1) (反码)
其中适用哪种是实现定义的,以及带符号位为1且所有值位均为0(对于前两者)或带符号位和所有值位均为1(对于反码),是陷阱表示还是常规值,也是实现定义的。对于符号-大小和反码,如果该表示是正常值,则称为负零。
这意味着使用反码或符号-大小的实现对于给定大小的整数类型,必须具有特定表示形式,该表示形式必须是负零或陷阱表示。然后由实现选择其中之一适用。
例如,假设一个系统具有符号-大小表示和没有填充的32位 int
。那么如果支持,则将成为负零的表示为 0x80000000
。
现在假设执行了以下操作:
int x = 0x7fffffff;
x = ~x;
如果实现支持负零,~
运算符将生成 -0
作为结果并将其存储在 x
中。如果不支持,则创建陷阱表示,并按照第4段调用未定义的行为。