整数:
32位int数据类型可以保存-2,147,483,648到2,147,483,647范围内的整数值。您也可以将此数据类型称为signed int或signed。
无符号整型:
32比特不带负数号的int资料类型可以储存0到4,294,967,295范围内的整数值。您也可以将此资料类型简称为不带负数号。
好吧,但是,在实践中:
int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
printf("%d, %d, %u, %u", x, y, x, y);
// -1, -1, 4294967295, 4294967295
没什么区别,我有点糊涂了
9条答案
按热度按时间tpxzln5u1#
这里有一个隐式强制转换,因为你告诉
printf
应该使用什么类型。试试这件:
kxxlusnw2#
是的,因为在您的情况下,它们使用the same representation。
位模式
0xFFFFFFFF
在解释为32 b有符号整数时看起来像-1,在解释为32 b无符号整数时看起来像4294967295。它和
char c = 65
一样,如果你把它解释成一个有符号整数,它就是65,如果你把它解释成一个字符,它就是a
。正如R和pmg所指出的,从技术上讲,传递与格式说明符不匹配的参数是未定义的行为,所以程序可以做任何事情(从打印随机值到崩溃,再到打印“正确”的东西,等等)。
标准以
7.19.6.1-9
指出如果转换规范无效,则行为不完整。如果任何参数不是相应转换规范的正确类型,则行为不完整。
ndasle7k3#
这两种运算在内存和寄存器中的存储方式没有区别,没有带符号和不带符号版本的int寄存器,也没有带符号的信息与int一起存储,只有在执行数学运算时才会有区别,CPU中内置了带符号和不带符号版本的数学运算,带符号性告诉编译器使用哪个版本。
gijlo24d4#
问题在于您调用了Undefined Behaviour。
当您调用UB时,任何事情都可能发生。
作业还可以;在第一行中有一个隐式转换
但是,对
printf
的调用是不正确的%
说明符与参数类型不匹配是UB。在您的情况下,您可以提供1
int
、1unsigned int
、1int
和1unsigned int
,以此顺序指定2int
和2unsigned int
。别做傻事!
pjngdqdw5#
int
和unsigned int
的内部表示是相同的。因此,当您将相同的格式字符串传递给
printf
时,它将被打印为相同的格式。但是,当您比较它们时,会发现它们之间存在差异。请考虑:
这也是一个警告,因为在比较有符号整数和无符号整数时,其中一个将被隐式转换以匹配类型。
edqdpe6u6#
二进制表示是密钥。示例:十六进制无符号整数
它表示
4,294,967,295
的十进制正数。但我们也需要一种表示负数的方法。所以大脑决定用二进制补码。简而言之,他们取最左边的位,并决定当它是1(后面至少还有一个其他位设置为1)时,数字将是负数。而最左边的位设置为0时,数字将是正数。现在让我们看看会发生什么再加上我们最终达到的数字。
带符号整数的最大正数。让我们再加1位(二进制加法会向左溢出,在本例中,所有位都设置为1,因此我们停留在最左边的位)
所以我想简而言之,我们可以说,一个允许负数,而另一个不允许,因为**符号位,**或者最左边的位,或者最高有效位。
zpjtge227#
他问的是 * 真实的 * 的区别。当你谈论未定义的行为时,你是在语言规范提供的保证水平上--它与现实相差甚远。要了解真正的区别,请查看以下片段(当然这是UB,但它在你最喜欢的编译器上定义得很完美):
ryevplcw8#
类型只是告诉你位模式应该代表什么。位只是你对它们的理解。相同的序列可以用不同的方式解释。
wvt8vs2t9#
printf
函数 * 解释 * 您根据匹配位置的格式说明符传递给它的值。如果您告诉printf
您传递的是int
,但传递的是unsigned
,printf
会将其中一个重新解释为另一个,并打印您看到的结果。