我花了一些时间仔细研究标准引用文献,但无法找到以下答案:

  • 在C/C++标准上是否从技术上保证给定有符号整数类型S和其无符号拷贝U,每个可能的S的绝对值始终小于或等于U的最大值?

  • 我得到的最接近的是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,答案是否定的,没有这样的保证。

    我将讨论intunsigned int类型;这同样适用于任何一对对应的有符号和无符号类型(charunsigned 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"更好的错误消息。)

    10-04 14:26
    查看更多