c-将负数分配给一个无符号的int?

在C编程语言中,unsigned int仅用于存储正值。 但是,当我运行以下代码时:

unsigned int x = -12;
printf("%d", x);

输出仍然是-12。 我以为应该打印出来:12,还是我误会了什么?

ipkiss asked 2020-01-14T08:09:14Z
14个解决方案
62 votes

等号右边的x设置为有符号整数(大小可能为32位),并将具有十六进制值unsigned int x = abs(-12);。编译器生成代码,以将该有符号整数移动到无符号整数x(该整数也是32) 位实体。 编译器假定您仅在等号右边具有一个正值,因此它将所有32位简单地移入xx现在具有值0xFFFFFFF4,如果将其解释为正数,则为4294967284。 但是%dprintf格式表示32位将被解释为有符号整数,因此您将得到-12。如果使用%u,它将被打印为4294967284

无论哪种情况,您都无法得到期望的结果,因为C语言“信任”代码编写者仅要求“明智”的事情。 这在C语言中很常见。如果您想为x分配一个值,并且不确定等式右边的值是否为正,则可以编写unsigned int x = abs(-12);并强制编译器生成代码以获取a的绝对值。 有符号整数,然后将其移至无符号整数。

Tim Oltrogge answered 2020-01-14T08:09:29Z
30 votes

该整数是未签名的,但是您已告诉printf将其视为带符号的整数。

尝试

unsigned int x = -12; printf("%u", x);

它不会打印“ 12”,但是会打印一个无符号整数减11的最大值。

对读者的练习是找出原因:)

Binary Worrier answered 2020-01-14T08:10:02Z
17 votes

将%d传递给printf告诉printf将参数视为有符号整数,而不管您实际传递了什么。 使用%u打印为未签名。

Erik answered 2020-01-14T08:10:23Z
6 votes

这都与价值的解释有关。

如果假设使用16位有符号和无符号整数,则此处的一些示例并非完全正确,而是说明了这一概念。

0000 0000 0000 1100 unsigned int和signed int值12

1000 0000 0000 1100带符号的int值-12,以及一个大的无符号整数。

对于带符号整数,左侧的位是符号位。0 =正1 =负数

对于无符号整数,没有符号位。左边的位可以让您存储更大的数字。

因此,您没有看到期望的原因是。

unsigned int x = -12,将-12作为整数,并将其存储到x中。 x是无符号的,所以标志性的东西现在已成为价值的一部分。

使用printf可以告诉编译器希望如何显示值。

%d表示将其显示为有符号的int。%u表示将其显示为无符号整数。

c使您可以执行此类操作。 您由程序员控制。

有点像枪支。这是一个工具。您可以正确使用它来处理某些情况,或错误地去除了您的脚趾之一。

一种可能有用的情况是以下

unsigned int allBitsOn = -1;

该特定值将所有位设置为1

1111 1111 1111 1111

有时会很有用。

EvilTeach answered 2020-01-14T08:11:54Z
4 votes
printf('%d', x); 

表示打印有符号整数。 您必须改为编写以下代码:

printf('%u', x);

另外,它仍然不会打印“ 12”,而是“ 4294967284”。

Linus Kleen answered 2020-01-14T08:12:18Z
3 votes

它们确实存储正值。 但是您将(非常高的)正值输出为一个有符号整数,因此它会再次被重新解释(以实现定义的方式,我可能会添加)。

请改用格式标志"%u

Lightness Races in Orbit answered 2020-01-14T08:12:42Z
3 votes

您的程序具有未定义的行为,因为您将错误的类型传递给了printf(您告诉它您将传递一个int,但传递了一个unsigned int)。 让自己感到幸运的是,实现的“最简单”操作只是默默地打印了错误的值,而不跳转到执行有害操作的代码...

R.. answered 2020-01-14T08:13:03Z
2 votes

您缺少的是printf(“%d”,x)期望x被签名,因此,尽管您为x分配了-12,但它被解释为2的补数,这将是一个很大的数字。但是,当您将这个非常大的数字传递给printf时,它会将其解释为带符号,从而正确地将其转换回-12。

打印print f中无符号的正确语法是“%u”-试试看,看看它能做什么!

Elemental answered 2020-01-14T08:13:28Z
1 votes

将负值分配给无符号int不会计算负数的绝对值:它将负值的二进制表示形式解释为无符号int,即4294967284(2 ^ 32-12)。

printf(“%d”)执行相反的解释。 这就是程序显示-12的原因。

mouviciel answered 2020-01-14T08:13:53Z
1 votes

int和unsigned int用于分配多个字节来存储值。

编译器应发出有关有符号不匹配的警告,但实际上并不会影响代表值-12的内存中的位。

%x,%d,%u等告诉编译器在打印时如何中断许多位。

trevor answered 2020-01-14T08:14:22Z
1 votes

当您尝试显示int值时,会将其传递给(int)参数而不是(unsigned int)参数,这将导致它输出-12而不是4294967284。整数以十六进制格式存储,而-12则存储为int 与以十六进制格式表示的无符号int相同,为4294967284。这就是为什么“%u”输出正确的值而不是“%d”的原因。这取决于您的参数类型。祝您好运!

Vern01 answered 2020-01-14T08:14:43Z
1 votes

-12采用16位2的补码格式。 这样做:如果(x&0x8000){x =〜x + 1; }这会将2的补语-ve号转换为等效的+ ve号。 祝好运。

Nichola Tesla answered 2020-01-14T08:15:03Z
0 votes

当编译器将-12隐式转换为无符号整数时,基础二进制表示形式保持不变。 这种转换纯粹是语义上的。 二进制补码整数的符号位变为无符号整数的最高有效位。 因此,当printf将无符号整数视为带有%d的有符号整数时,它将看到-12。

Faust answered 2020-01-14T08:15:24Z
0 votes

通常,当只能存储正数时,不会显式存储负数,但会存储其2的补码。 在这里以相同的方式将-12的2的补码存储在'x'中,您可以使用%u来获取它。

King answered 2020-01-14T08:15:44Z
translate from https://stackoverflow.com:/questions/5169692/assigning-negative-numbers-to-an-unsigned-int