【问题标题】:Is it guaranteed that assigning -1 to an unsigned type yields the maximum value?是否保证将 -1 分配给无符号类型会产生最大值?
【发布时间】:2021-01-28 09:42:51
【问题描述】:

我发现了一些关于这个特定主题的问题,但都是关于 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 = -1var 设置为它可以容纳的最大值?这个程序是否保证打印“是”?

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

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

【问题讨论】:

  • 但实际上,它不是 stackoverflow.com/questions/1667963/… 的副本吗?我认为不是,因为您提到了它,但该答案字面意思是The requirements on unsigned arithmetic guarantee that casting -1 to an unsigned type will produce the largest number possible for the target type,答案也跟着This is the same in C and C++
  • @KamilCuk 我认为最好保留这一点,因为它只关注 C,而且您的回答非常好,并且通过引用直截了当。
  • @KamilCuk 它甚至明确引用了 C99 标准:C99, §6.2.5/9 所以它对 C 绝对有效。
  • 好吧,我们现在有了明确的 C 版本
  • @KamilCuk 我个人不喜欢投票结束 C 问题作为 C++ 问题的欺骗,只是因为 C++ 问题的答案提到它也适用于 C。

标签: c unsigned


【解决方案1】:

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

是的。

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

是的。

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

否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上反复加减一,直到值在新类型的范围内

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

【讨论】:

    【解决方案2】:

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

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

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

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

    所以给定unsigned long var = -1;,值就变成了

    • -1 然后将 unsigned long 的最大值加一
    • 意思是-1 + ULONG_MAX+1 = U_LONG_MAX

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

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

    【讨论】:

    • 您也可以使用 stdint.h 类型,因为它们保证使用 2 的补码。 uint32_t var = (int32_t)0xFFFFFFFFF; 本身定义良好,但功能失调的外来系统实际上不需要提供 int32_t,它是一个可选类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    相关资源
    最近更新 更多