我花了一些时间仔细研究标准引用文献,但无法找到以下答案:
我得到的最接近的是C99标准的6.2.6.2节(C++的措词对我来说比较神秘,我认为它们对此等效):
因此,在假设的4位带符号/无符号整数类型中,是否有什么方法可以阻止无符号类型具有1个填充位和3个值位,以及带符号类型具有3个值位和1个符号位?在这种情况下,无符号的范围将是[0,7],而有符号的范围将是[-8,7](假定为2的补码)。
万一有人好奇,我现在依靠的是一种提取负整数的绝对值的技术,该负整数包括首先转换为无符号对应项的强制类型转换,然后是一元减运算符的应用(例如,- 3通过强制转换变成4,然后通过一元减3变成3)。这将在上面的-8示例中中断,该示例无法以unsigned类型表示。
编辑:感谢您在Keith和Potatoswatter下面的答复。现在,我的最后一个疑问是标准措辞中“子范围”的含义。如果这意味着严格的“小于”包含,则上面的示例和下面的Keith的示例均不符合标准。如果该子范围可能是整个无符号范围,那么它们就是。
最佳答案
对于C,答案是否定的,没有这样的保证。
我将讨论int
和unsigned int
类型;这同样适用于任何一对对应的有符号和无符号类型(char
和unsigned char
除外,两者都不能具有填充位)。
在引用的部分中,该标准隐含地保证UINT_MAX >= INT_MAX
,这意味着每个非负int
值都可以表示为unsigned int
。
但是以下内容完全合法(我将使用**
表示幂):
CHAR_BIT == 8
sizeof (int) == 4
sizeof (unsigned int) == 4
INT_MIN = -2**31
INT_MAX = +2**31-1
UINT_MAX = +2**31-1
这意味着
int
具有1个符号位(必须)和31个值位,是普通的2补码表示形式,而unsigned int
具有31个值位和一个填充位。设置该填充位的unsigned int
表示可能是陷阱表示,或者是未设置填充位的值的其他表示。这可能适用于支持2的补码有符号算术,但对无符号算术的支持较差的机器。
鉴于这些特征,
-INT_MIN
(数学值)超出了unsigned int
的范围。另一方面,我严重怀疑是否有这样的现代系统。该标准允许填充位,但是填充位很少,而且我不希望它们变得更常见。
您可以考虑添加以下内容:
#if -INT_MIN > UINT_MAX
#error "Nope"
#endif
到您的源代码,因此仅当您可以执行所需的操作时,它才会编译。 (当然,您应该想到比
"Nope"
更好的错误消息。)