“ int”和“ unsignedint”之间的真正区别

返回文章页面

位 int 数据类型可以将整数值保存在 -2,147,483,648至2,147,483,647 有符号的整型或有符号的。

无符号 int :

32位无符号整数数据 类型可以保存0到4,294,967,295之间的整数值 也可以简单地将此数据类型称为 unsigned。

好吧,但实际上:

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
printf("%d, %d, %u, %u", x, y, x, y);
// -1, -1, 4294967295, 4294967295

没什么区别,我有点糊涂了。

292942 次浏览

是的,因为在你的情况下,他们使用 同样的表述

位模式 0xFFFFFFFF在被解释为32b 有符号整数时看起来像 -1,而在被解释为32b 无符号整数时看起来像4294967295。

char c = 65是一样的。如果将其解释为有符号整数,则为65。如果你把它解释成一个字符,它就是 a


正如 R 和 pmg 指出的那样,从技术上讲,传递与格式说明符不匹配的参数是有未定义行为的。所以这个程序可以做任何事情(从打印随机值到崩溃,到打印“正确”的东西,等等)。

标准在 7.19.6.1-9中指出了这一点

如果转换规范无效,则行为未定义。 < strong > If 任何参数都不是相应转换的正确类型 规范,行为是未定义的。

类型只是告诉您位模式应该表示什么。那些碎片只是你自己制造出来的。相同的序列可以用不同的方式解释。

printf函数 翻译是根据格式说明符在匹配位置传递给它的值。如果您告诉 printf您传递了一个 int,但是传递了 unsigned,那么 printf将重新解释其中一个为另一个,并打印您所看到的结果。

呵呵。你在这里有一个隐含的演员阵容,因为你告诉 printf期待什么样的类型。

试试这个:

unsigned int x = 0xFFFFFFFF;
int y = 0xFFFFFFFF;


if (x < 0)
printf("one\n");
else
printf("two\n");
if (y < 0)
printf("three\n");
else
printf("four\n");

intunsigned int的内部表示是相同的。

因此,当您将相同的格式字符串传递给 printf时,它将被打印为相同的格式。

然而,当你比较它们的时候,它们是有区别的。 考虑一下:

int x = 0x7FFFFFFF;
int y = 0xFFFFFFFF;
x < y // false
x > y // true
(unsigned int) x < (unsigned int y) // true
(unsigned int) x > (unsigned int y) // false

这也是一个警告,因为当比较有符号和无符号整数时,其中一个将隐式强制转换以匹配类型。

问题是您调用了 未定义行为


当您调用 UB时,任何事情都可能发生。

赋值是可以的; 在第一行中有一个隐式转换

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;

但是,打到 printf的电话,不好吗

printf("%d, %d, %u, %u", x, y, x, y);

UB%说明符和参数类型不匹配。
在您的情况下,您指定2个 int和2个 unsigned int在这个顺序提供1个 int,1个 unsigned int,1个 int和1个 unsigned int


不要做 UB

他正在询问 真的的差异。 当你谈论未定义行为的时候,你是在语言规范所提供的保证水平上——这是远离现实的。 为了理解真正的区别,请检查下面的代码片段(当然这是 UB,但是它在你最喜欢的编译器上有完美的定义) :

#include <stdio.h>


int main()
{
int i1 = ~0;
int i2 = i1 >> 1;
unsigned u1 = ~0;
unsigned u2 = u1 >> 1;
printf("int         : %X -> %X\n", i1, i2);
printf("unsigned int: %X -> %X\n", u1, u2);
}

两者在如何存储在内存和寄存器中没有区别,没有整型寄存器的有符号和无符号版本,没有整型寄存器存储的有符号信息,只有当你执行数学运算时,差异才变得相关,有符号和无符号版本的数学运算内置在 CPU 和有符号告诉编译器使用哪个版本。

二进制表示是关键。示例: 十六进制中的无符号整型

 0XFFFFFFF = translates to = 1111 1111 1111 1111 1111 1111 1111 1111

它以十进制正数表示 4,294,967,295。 但我们也需要一种表示负数的方法。 所以大脑决定两个互补。 简而言之,他们取最左边的位,并决定当它是1(后面至少有一个其他位设置为1)的数字将是负的。 最左边的位设置为0,数字为正。 现在让我们看看会发生什么

0000 0000 0000 0000 0000 0000 0000 0011 = 3

加上我们最终达到的数字。

0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645

有符号整数的最高正数。 让我们再添加1位(二进制加法将溢出传递到左边,在这种情况下,所有位都设置为1,因此我们降落在最左边的位)

1111 1111 1111 1111 1111 1111 1111 1111 = -1

所以我想简而言之,我们可以说区别在于一个允许负数,而另一个不允许。 因为 符号位或者最左边的位或者最高有效位。