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

时间:2012-01-28 13:04:32

标签: c

INT

32位int数据类型可以包含范围内的整数值  -2,147,483,648至2,147,483,647。您也可以参考此数据类型  签名为int或签名。

unsigned int

32位无符号整数数据  type可以保存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

没有区别,O.o。我有点困惑。

9 个答案:

答案 0 :(得分:44)

鹤鹤。你有一个隐式演员,因为你告诉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");

答案 1 :(得分:24)

是的,因为在您的情况下,他们使用the same representation

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

char c = 65相同。如果你把它解释为有符号整数,它就是65.如果你把它解释为一个字符a


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

标准指出7.19.6.1-9

  

如果转换规范无效,则行为未定义。 如果   任何参数都不是相应转换的正确类型   具体而言,这种行为是未定的。

答案 2 :(得分:16)

两者在内存和寄存器中的存储方式没有区别,没有有符号和无符号版本的int寄存器,没有用int存储的签名信息,差异只在执行数学运算时才变得相关,内置于CPU中的数学操作符号和未签名版本,签名告诉编译器使用哪个版本。

答案 3 :(得分:7)

问题是您调用了Undefined Behaviour


当您调用 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个{{ 1}}。


不要 UB

答案 4 :(得分:3)

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

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

答案 5 :(得分:2)

他在询问真正的差异。 当你谈论未定义的行为时,你处于语言规范提供的保证级别 - 它远非现实。 要了解真正的区别,请检查此片段(当然这是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);
}

答案 6 :(得分:1)

该类型只是告诉您应该表示的位模式。这些比特只是你对它们所做的。相同的序列可以用不同的方式解释。

答案 7 :(得分:1)

printf函数根据匹配位置的格式说明符解释传递的值。如果您告诉printf您传递的是int,而是传递unsignedprintf会将其重新解释为另一个,并打印您看到的结果。< / p>

答案 8 :(得分:0)

这个很直接。二进制表示是它被提及但从未显示的键。 在HEX中无符号,如果0XFFFFFFF =机器代码= 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295 数字的正表示。 这一切都很好,但我们需要一种方法来表示负数。 所以大脑决定两个补码。 这意味着什么呢,简而言之,他们取最左边的数字并决定当它是1(然后是所有的直到你到达最左边的最高位),如果它是0则数字将为负数。 现在让我们来看看 0000 0000 0000 0000 0000 0000 0000 0011 = 3 会发生什么。 现在让我们继续增加这个数字 0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645 带有signed int的最高正数。 让我们加1(这里你可能想要查找二进制加法) 我们必须一直带着这一个。 1111 1111 1111 1111 1111 1111 1111 1110 = -1 所以我想简而言之,我们可以说区别是允许负数而另一个不允许,这是由于符号位或最左位或最高位。