无符号vs有符号范围保证

blu*_*rni 9 c c++

我花了一些时间仔细阅读标准参考文献,但我无法找到以下答案:

  • 在技​​术上是否由C/C++标准保证,给定有符号整数类型S及其无符号对应物U,每个可能S的绝对值总是小于或等于U的最大值?

我得到的最接近的是C99标准的第6.2.6.2节(C++的措辞对我来说更加神秘,我认为它们与此相当):

对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位.(...)作为值位的每个位应具有与相应无符号类型的对象表示中的相同位相同的值(如果在有符号类型中有M个值位且Nin为无符号类型,则M≤ N).

因此,在假设的4位有符号/无符号整数类型中,是否有任何阻止无符号类型具有1个填充位和3个值位的东西,以及具有3个值位和1个符号位的带符号类型?在这种情况下,无符号的范围是[0,7],对于有符号,它将是[-8,7](假设是2的补码).

如果有人好奇,我现在依赖于一种技术来提取负整数的绝对值,该负整数包括第一个强制转换为无符号对应物,然后应用一元减号运算符(例如 - 3通过强制转换为4,然后通过一元减去3).这将破坏上面的例子-8,它无法用无符号类型表示.

编辑:感谢Keith和Potatoswatter下面的回复.现在,我最后的疑问是关于标准措辞中"子范围"的含义.如果它意味着严格的"小于"包含,那么我上面的例子和下面的Keith不符合标准.如果子范围可能是整个无符号范围,那么它们就是.

Kei*_*son 7

对于C,答案是否定的,没有这样的保证.

我将讨论类型intunsigned 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
Run Code Online (Sandbox Code Playgroud)

这意味着它int具有1个符号位(必须)和31个值位,一个普通的2位补码表示,并unsigned int具有31个值位和一个填充位. unsigned int具有该填充位集的表示可以是陷阱表示,或者是未填充填充位的值的额外表示.

这可能适用于支持二进制补码有符号算术的机器,但对无符号算术的支持较差.

鉴于这些特征,-INT_MIN(数学值)超出范围unsigned int.

另一方面,我严重怀疑有这样的现代系统.填充位是标准允许的,但非常罕见,我不希望它们变得更常见.

您可以考虑添加以下内容:

#if -INT_MIN > UINT_MAX
#error "Nope"
#endif
Run Code Online (Sandbox Code Playgroud)

到你的来源,所以只有你能做你想做的事情才会编译.(当然,你应该想到一个更好的错误信息"Nope".)

  • 有一对整数类型有保证,即`signed char`和`unsigned char`.这些不允许有填充位.所以`SCHAR_MIN`的否定值总是适合`unsigned char`. (2认同)