将负数分配给unsigned int?

ipk*_*iss 52 c

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

unsigned int x = -12;
printf("%d", x);
Run Code Online (Sandbox Code Playgroud)

输出仍为-12.我认为应该打印出来:12,还是我误解了什么?

小智 62

-12您等号右边的标志是设置为一个有符号整数(大小大概32位),将有十六进制值0xFFFFFFF4.编译器生成代码以将此有符号整数移动到无符号整数x,该整数也是32位实体.编译器假设您只在等号右侧有一个正值,因此它只是将所有32位移入x.x现在有一个值0xFFFFFFF4,4294967284如果被解释为正数.但是32位的printf格式%d将被解释为有符号整数,所以你得到了-12.如果您使用%u它将打印为4294967284.

在任何一种情况下,你都没有得到你所期望的,因为C语言"信任"代码的作者只是要求"明智的"事情.这在C中很常见.如果你想为一个值赋值x并且不确定equals右侧的值是否为正,那么你可以编写unsigned int x = abs(-12);并强制编译器生成代码以获取有符号整数的绝对值在将其移动到无符号整数之前.

  • 其中大部分在技术上都是错误的.在`unsigned int x = -12;`中,`-12`是一个类型为`int`的整型常量表达式.通过向该值重复添加(或减去)"UINT_MAX + 1",将其转换为"unsigned int",直到获得0和"UINT_MAX"(包括两者)之间的值,该值是转换的结果.在一些补码或符号和大小的机器上,它改变了值的位模式; 在更常见的二进制补码机器上,它只是对相同位模式的不同解释. (14认同)
  • 但是,该部分完全由标准定义,在`unsigned int x = -12;`之后,`x`的值必须始终为'UINT_MAX - 11`.下一行,`printf("%d",x);`调用未定义的行为,因为`%d`转换说明符需要一个带符号的`int`,而'x`的值在`unsigned int`中是_not_表示的和`int`.当然,通常的行为是对位模式的重新解释,在这种情况下会产生`-11`,在32位`int`s,`-2147483636`的符号和数量上.在两个补充机器上观察到的行为. (8认同)

Bin*_*ier 30

int是未定义的,但是你已经告诉printf它将它视为一个带符号的int.

尝试

unsigned int x = -12; printf("%u", x);
Run Code Online (Sandbox Code Playgroud)

它不会打印"12",但会打印unsigned int减去11的最大值.

练习给读者是找出原因:)

  • "11或12"是错误的.结果定义明确,是'UINT_MAX-11`,而不是'UINT_MAX-12`. (4认同)
  • @R:我不记得它是max-11**还是**max - 12,因此我说"减11或12"(技术上是正确的,因为它是其中之一).谢谢你指出它是-11,我会改变回答这一点,谢谢. (4认同)

Eri*_*rik 17

将%d传递给printf会告诉printf将参数视为有符号整数,而不管实际传递的是什么.使用%u打印为无符号.


Evi*_*ach 7

这一切都与价值的解释有关.

如果你假设16位有符号和无符号整数,那么这里有一些不完全正确的例子,但是展示了这个概念.

0000 0000 0000 1100 unsigned int和signed int值12

1000 0000 0000 1100 signed int value -12,以及一个大的无符号整数.

对于有符号整数,左边的位是符号位.0 =正1 =负

对于无符号整数,没有符号位.左手位,让你存储一个更大的数字.

所以你没有看到你期待的是那个原因.

unsigned int x = -12,将-12作为整数,并将其存储到x中.x是无符号的,所以什么是符号位,现在是一个值.

printf允许您告诉编译器您希望如何显示值.

%d表示将其显示为已签名的int.%u表示将其显示为无符号整数.

c让你做这种事情.你是程序员掌控的.

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

一个可能有用的案例如下

unsigned int allBitsOn = -1;

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

1111 1111 1111 1111

这有时很有用.