负数分配给一个unsigned int?
在C编程语言中, unsigned int
只用于存储正值。 但是,当我运行下面的代码:
unsigned int x = -12; printf("%d", x);
输出仍然是-12。 我以为应该打印出来12,还是我误解了一些东西?
等号右边的-12
被设置为一个有符号的整数(可能是32位),并且将有hex值0xFFFFFFF4
。 编译器生成代码将这个有符号的整数移动到你的无符号整数x
,这个整数也是一个32位实体。 编译器假定你只对等号右边有一个正值,所以它只是把所有的32位移到x
。 现在x
的值为0xFFFFFFF4
,如果解释为正数,则为4294967284
。 但%d
的printf
格式说32位被解释为一个有符号的整数,所以你得到-12
。 如果您使用了%u
,它将打印为4294967284
。
无论哪种情况,你都没有得到你所期望的,因为C语言“信任”代码的作者只是要求“明智”的东西。 这在C中是很常见的。如果你想给x
赋一个值,但不确定等号右边的值是否为正数,你可以写成unsigned int x = abs(-12);
并强制编译器生成代码,以将有符号整数的绝对值移到无符号整数。
int是unsinged的,但是你已经告诉printf
将它看作一个带符号的int。
尝试
unsigned int x = -12; printf("%u", x);
它不会打印“12”,但会打印无符号整数减去11的最大值。
运动给读者是要找出为什么:)
将%d传递给printf会告诉printf把参数当作一个有符号的整数,而不pipe你实际传递的是什么。 使用%u作为无符号打印。
这一切都与价值的解释有关。
如果你假设16位有符号和无符号整数,那么这里有一些不完全正确的例子,但是展示了这个概念。
0000 0000 0000 1100无符号整数,有符号整数值12
1000 0000 0000 1100有符号整型值-12,和一个大的无符号整数。
对于有符号整数,左边的位是符号位。 0 =正面1 =负面
对于无符号整数,没有符号位。 左边的位,让你存储一个更大的数字。
所以你没有看到你期望的是这个原因。
unsigned int x = -12,以-12为整数,并将其存储到x中。 x是无符号的,所以什么是符号位,现在是一个值。
printf让你告诉编译器你想如何显示一个值。
%d表示将其显示为有符号整数。 %u表示将它显示为无符号整型。
C让你做这种东西。 程序员在掌控之中
有点像枪支。 这是一个工具。 您可以正确使用它来处理某些情况,或不正确地删除您的一个脚趾。
一个可能有用的情况是以下
unsigned int allBitsOn = -1;
该特定值将所有位设置为1
1111 1111 1111 1111
有时可能有用。
printf('%d', x);
意味着打印一个有符号的整数。 你将不得不写这个:
printf('%u', x);
此外,它仍然不会打印“12”,这将是“4294967284”。
他们确实存储正面价值。 但是你输出(非常高)正值作为一个有符号的整数,所以它会被重新解释(以实现定义的方式,我可能会添加)。
使用格式标志"%u
代替。
你的程序有未定义的行为,因为你把错误的types传递给了printf
(你告诉它你要传递一个int
但是你传递了一个unsigned int
)。 考虑一下你自己的幸运,即实现所做的“最简单”的事情只是默默地打印错误的值,而不是跳转到一些有害的代码。
你所缺less的是printf(“%d”,x)期望x被签名,所以尽pipe你给-x指定了-12,它将被解释为2的补码,这将是一个非常大的数字。 但是,如果将这个非常大的数字传递给printf,则会将其解释为signed,从而将其正确转换回-12。
在打印f中打印无符号的正确语法是“%u” – 试试看看它做了什么!
将一个负值分配给一个无符号整数不会计算出负数的绝对值:它将解释为一个无符号整数,即负值的二进制表示forms,即4294967284(2 ^ 32 – 12)。
printf(“%d”)执行相反的解释。 这就是为什么你的程序显示-12。
当你试图显示int值时,你将它传递给一个(int)参数而不是一个(unsigned int)参数,并且导致它打印-12而不是(4294967284)。 整数以hex格式存储 ,-12为int与hex格式的无符号整数4294967284相同。这就是为什么“%u”打印所需的正确值而不是“%d”..这取决于您的参数types。良好的运气!
当编译器将-12隐式转换为无符号整数时,底层二进制表示保持不变。 这种转换纯粹是语义的。 二进制补码整数的符号位成为无符号整数的最高有效位。 因此,当printf将无符号整数视为带有%d的有符号整数时,它将看到-12。
在一般情况下,只有正数可以被存储,负数不被明确地存储,但是它们的二进制补码被存储。 在这里用相同的方式,-12的二进制补码将被存储在“x”中,并使用%u
来获得它。
int和unsigned int用于分配一些字节来存储一个值。
编译器应该给出关于有符号不匹配的警告,但它确实不会影响内存中代表值-12的位。
%x,%d,%u等告诉编译器在打印时如何中断许多位。