在C编程语言中,unsigned int
仅用于存储正值。但是,当我运行以下代码时:
unsigned int x = -12;
printf("%d", x);
输出仍为-12。我认为应该打印出来:12,还是我误解了什么?
答案 0 :(得分:61)
等号右边的-12
被设置为有符号整数(大小可能是32位),并且将具有十六进制值0xFFFFFFF4
。编译器生成代码以将此有符号整数移动到无符号整数x
,该整数也是32位实体。编译器假设您只在等号右侧有一个正值,因此它只是将所有32位移动到x
。 x
现在具有值0xFFFFFFF4
,如果被解释为正数,则为4294967284
。但printf
格式%d
表示32位将被解释为有符号整数,因此您得到-12
。如果您使用过%u
,则会将其打印为4294967284
。
在任何一种情况下,你都没有得到你所期望的,因为C语言“信任”代码的作者只是要求“明智的”事情。这在C中很常见。如果您想为x
分配一个值,并且不确定equals右侧的值是否为正,则可以编写unsigned int x = abs(-12);
并强制编译器生成代码,用于在将有符号整数移动到无符号整数之前获取有符号整数的绝对值。
答案 1 :(得分:30)
int是unsinged,但你已告诉printf
将其视为已签名的int。
尝试
unsigned int x = -12; printf("%u", x);
它不会打印“12”,但会打印unsigned int减去11的最大值。
向读者练习是找出原因:)
答案 2 :(得分:17)
将%d传递给printf告诉printf将参数视为有符号整数,而不管实际传递的是什么。使用%u打印为无符号。
答案 3 :(得分:6)
这一切都与价值的解释有关。
如果你假设16位有符号和无符号整数,那么这里有一些不完全正确的例子,但是展示了这个概念。
<00> 0000 0000 0000 1100 unsigned int,signed int value 121000 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
有时可能很有用。
答案 4 :(得分:4)
printf('%d', x);
表示打印有符号整数。你必须写这个:
printf('%u', x);
此外,它仍然不会打印“12”,它将是“4294967284”。
答案 5 :(得分:3)
他们存储正值。但是你输出(非常高)正值作为有符号整数,所以它再次被重新解释(以实现定义的方式,我可能会添加)。
请改为使用格式标记"%u
。
答案 6 :(得分:3)
您的程序有未定义的行为,因为您将错误的类型传递给printf
(您告诉它您将传递int
,但您传递了unsigned int
)。认为自己很幸运,实现的“最简单”的事情就是默默地打印错误的值而不是跳转到某些有害的代码......
答案 7 :(得分:2)
你缺少的是printf(“%d”,x)期望x被签名,所以尽管你将-12分配给x它被解释为2的补码,这将是一个非常大的数字。 但是,当你将这个非常大的数字传递给printf时,它会将其解释为signed,从而正确地将其转换回-12。
打印未签名的打印f的正确语法是“%u” - 试试这个,看看它的作用!
答案 8 :(得分:1)
将负值赋值给unsigned int不会计算负数的绝对值:它将负值的二进制表示形式解释为unsigned int,即4294967284(2 ^ 32 - 12)。
printf(“%d”)执行相反的解释。这就是您的程序显示-12的原因。
答案 9 :(得分:1)
当您尝试显示int值时,您将其传递给(int)参数而不是(unsigned int)参数,这会导致它打印-12而不是4294967284. 整数以十六进制存储对于int,格式和-12与十六进制格式的unsigned int的4294967284相同。 这就是为什么“%u”打印出你想要的正确值而不是“%d”..这取决于你的论点类型...... GOOD LUCK!
答案 10 :(得分:1)
-12的格式为16位2。这样做: 如果(x&0x8000){x =〜x + 1; } 这会将2的补语-ve号转换为等效的+ ve号。祝你好运。
答案 11 :(得分:0)
当编译器将-12隐式转换为无符号整数时,基础二进制表示保持不变。这种转换纯粹是语义上的。二进制补码整数的符号位成为无符号整数的最高有效位。因此,当printf将无符号整数视为带有%d的有符号整数时,它将显示-12。
答案 12 :(得分:0)
在一般情况下,只能存储正数时,不会明确存储负数,而是存储它们的2的补码。在这里以相同的方式,-12的2的补码将存储在'x'中,并使用%u
来获得它。
答案 13 :(得分:0)
int和unsigned int用于分配一些字节来存储一个值。
编译器应该发出有关签名不匹配的警告,但它确实不会影响内存中代表值-12的位。
%x,%d,%u等告诉编译器在打印时如何中断多个位。