是否保证将 -1 分配给无符号类型会产生最大值?

问题描述

我发现了一些关于这个特定主题的问题,但它们都是关于 C++ 的。

How portable is casting -1 to an unsigned type?

converting -1 to unsigned types

Is it safe to assign -1 to an unsigned int to get the max value?

在阅读答案时,这似乎是 C 和 C++ 不同之处之一,这似乎很可能或至少不太可能。

问题很简单:

如果我用 unsigned char/short/int/long var 声明一个变量或使用任何其他无符号类型,如固定宽度、最小宽度等,那么是否保证 var = -1 会将 var 设置为它的最大值能把持住?该程序是否保证打印“是”?

#include <stdio.h>
#include <limits.h>

int main(void) {
    unsigned long var = -1;
    printf("%s\n",var == ULONG_MAX ? "Yes" : "No");
}

解决方法

是否保证将 -1 赋给无符号类型会产生最大值?

是的。

这个程序是否保证打印“是”?

是的。

这是一个转换,从 int -1unsigned long-1 不能表示为 unsigned long。来自C11 6.3.1.3p2

否则,如果新类型是无符号的,则通过重复加或减一个新类型可以表示的最大值来转换该值,直到该值在新类型的范围内

所以我们将一个 (ULONG_MAX + 1) 添加到 -1,我们得到 -1 + (ULONG_MAX + 1) = ULONG_MAX,它在 unsigned long 的范围内。

,

-1 (signed int) 到大型无符号类型的转换是明确定义的,根据 C17 6.3.1.3。

否则,如果新类型是无符号的,则通过重复添加或转换该值 比新类型可以表示的最大值多减一 直到该值在新类型的范围内60)

这里有一个有用的脚注 60)

  1. 这些规则描述的是数学值的算术运算,而不是给定类型表达式的值。

因此给定 unsigned long var = -1;,值变为

  • -1 然后将 unsigned long 的最大值加一
  • 含义 -1 + ULONG_MAX+1 = U_LONG_MAX

这是定义明确且可移植的行为。与从无符号到有符号的转换不同,它可以调用实现定义的行为。

此外,这与符号格式无关,因为应该使用数学值,而不是原始二进制值。如果你做了像 unsigned long var = (signed long)0xFFFFFFFFF; 这样的事情,那么对于具有 1 的补码或有符号幅度的奇异/虚构系统来说,这将是另一回事。