【问题标题】:Why unsigned int stills signed? [duplicate]为什么 unsigned int 仍然签名? [复制]
【发布时间】:2017-12-22 03:45:31
【问题描述】:

我创建了一个 unsigned int 和 unsigned char。然后我分配 -10 值,char 保持无符号并给我一个值 246,但 unsigned int 采用 -10 值。

#include <stdio.h>
int main ()
{


unsigned char a;
unsigned int b;
a=-10; 
b=-10;
printf("%d\t%d\n", a,b);

}

编译和执行我有这个:

246     -10

我不知道为什么 unsigned int 仍然签名,以及为什么 char 是 unsigned。

阅读《The C programming language 2nd edition》一书,我可以看到 char 在默认情况下可以是无符号的,具体取决于机器。

(我将 NetBSD 作为操作系统运行。)

为什么当我声明为 unsigned int 时 int 是有符号的,为什么 char 的值为 246?

这是编译器还是系统操作“功能”?

【问题讨论】:

  • 因为%d 用于有符号整数。
  • %d 告诉函数将该参数“解释”为有符号整数,无论​​其声明如何(只要它通过编译器的语义检查)
  • 使用%dprintfunsigned int 值大于INT_MAX 是非法的。行为未定义,输出无意义。就未定义的行为问“为什么”问题是没有意义的。
  • @AnT - 将%d 格式用于unsigned int 并非“非法”。它给出了未定义的行为。有区别。
  • @Peter:“英语词典”与此关系不大。语言规范明确允许编译器拒绝编译包含未定义行为的代码。这意味着在一般情况下,这可能与常规语法错误一样“非法”。或者它可能不是......

标签: c


【解决方案1】:

当您将无符号整数传递给%d 时,这是未定义的行为。 Wrong format specifier is UB.

如果你给一个无符号变量赋值一个负值,这很好,该值将取模UINT_MAX + 1(或UCHAR_MAX + 1),所以(-10) % (UCHAR_MAX + 1) = 256 - 10 = 246,b 是 4294967296 - 10 = 4294967286。无符号整数溢出需要回绕。

printf 解释这些数字时,发现 246 适合 %dsigned int 的格式说明符,4294967286 被重新解释为 -10。就是这样。

【讨论】:

  • 所以 int 确实不是未签名的,我认为它已签名,即使我声明为未签名。谢谢大家
  • @VMS 它确实未签名的。打印时将其重新解释为已签名。
  • 大声笑对不起,我想说“int 真的是无符号的”
  • "...4294967286 转换为 -10"。这是误导。标准printf 无法执行转换,因为它不知道源类型。它所能做的最好的就是重新解释。但形式上行为是未定义的。
  • @AnT 感谢您的指出。对不起我的英语不好:(
【解决方案2】:

当您将-10 分配给unsigned char 变量时,该值会以UCHAR_MAX + 1 为模减少,从而在您的平台上产生246。使用格式%d 打印unsigned char 值在大多数平台上都很好。该值被隐式转换为int,这是%d 格式的正确类型。所以,你应该看到246

当您将-10 分配给unsigned int 变量时,该值会以UINT_MAX + 1 为模减少,这会产生一些较大的值(取决于您平台上unsigned int 的范围)。使用格式%d 打印如此大的unsigned int 值(大于INT_MAX)会导致未定义行为。输出没有意义。

【讨论】:

    【解决方案3】:

    %d是用来打印signed int的说明符,所以并不奇怪。请改用%u

    http://www.cplusplus.com/reference/cstdio/printf/

    当您将负值分配给无符号变量时,您将溢出。这就是为什么你会得到奇怪的值。

    printf("%d", a) 表示将变量a 的内容并解释它作为一个有符号的int。

    哦,顺便说一句。您正在导致未定义的行为,这意味着确实没有理由问为什么会发生某些事情。未定义的行为将始终未定义。不惜一切代价避免它。请注意,唯一未定义的是 printf 语句。将超出范围的值分配给无符号变量是一种已定义的行为。然而,事实并非如此。 int a = UINT_MAX 将导致未定义的行为。

    【讨论】:

    • 246 4294967286 如果我使用 %u 代替,这就是我所拥有的
    • 它们是否减去了最大可能值的 10?为什么是这些数字?
    • @VMS - 因为这是标准所要求的。无符号整数类型的溢出使用模运算。所以-10 转换为unsigned 得到UINT_MAX + 1 - 10 的结果,其中UINT_MAX(在&lt;limits.h&gt; 中可用)是unsigned 可以表示的最大值。典型的 32 位 unsigned 类型的 UINT_MAX 等于 4294967295
    • @klutt 这就是我要问的原因,无符号意味着就像你说的变量不能处理负数,但 int 仍在处理它而 char 不能
    • @VMS 不,printf 语句将变量中的内容解释为有符号整数。这是有区别的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2021-08-07
    • 1970-01-01
    • 2012-09-09
    • 2010-12-24
    • 2018-08-25
    相关资源
    最近更新 更多