2012-01-28 90 views
29

INT之间的真正区别:“Int”和“无符号整型”

32位int数据类型可以在 -2147483648范围保持整数值到2,147,483,647。您也可以将这种数据类型 称为signed int或signed。

无符号整型

的32位无符号int数据 类型可在0范围内的保持整数值到4294967295。你也可以将这种数据类型简称为无符号。

好的,但是,在实践中:

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

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

+1

您需要考虑'int'和'unsigned int'的_binary_表示。 – Oded 2012-01-28 13:08:54

+1

这可能发生的真正原因是C是* weakly * * typed *语言。但'unsigned int'和'int'确实不同。 – cha0site 2012-01-28 13:13:55

+1

http://stackoverflow.com/questions/247873/signed-versus-unsigned-integers – 2012-01-28 13:18:09

回答

34

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

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

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

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


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

标准分出来的7.19.6.1-9

如果转换SPECI网络阳离子是无效的,行为是理解过程定义网络。 如果 对于相应的转换 规范,任何参数都不是正确的类型,则行为是不确定的。

+4

真正的原因是他使用%u来打印两者。 – 2012-01-28 13:11:10

+3

真正的原因是他**通过将非类型匹配的格式字符串传递给'printf'来调用未定义的行为**。我几乎想要对所有跳过这个的答案进行倒推,并指出与表示无关的东西... – 2012-01-28 13:33:07

+1

@R ..没错,格式和参数不匹配是未定义的行为。随时downvote,我不会介意:-) – cnicutar 2012-01-28 13:33:55

1

该类型只是告诉你位模式应该表示什么。这些位只是你所做的。相同的序列可以用不同的方式解释。

1

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

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 

这也可以是一个警告,因为当比较有符号和无符号整数其中一人将被隐式铸造相匹配的类型。

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 unsigned int


不要做UB

+0

-1,错误。这不是未定义的行为。查看C99第6.5.2.2节第6段。 – cha0site 2012-01-28 13:47:13

+1

@ cha0site:我具体地说,作业没问题:*第6.5.2.2节第6段*并不适用于我的答案。 UB在'printf'调用中:check [7.19.6.1](http://port70.net/~nsz/c/c99/n1256.html#7.19.6):“如果任何参数不是正确的类型对于相应的转换规范,行为是未定义的“。另外请注意'printf'是一个函数,其参数数量可变,根据原型进行转换是不可能的。 – pmg 2012-01-28 13:55:48

+0

C99 [6.5.2.2](http://port70.net/~nsz/c/c99/n1256.html#6.5.2.2)优先于此。正在进行整数升级。我可能误解了 - 可能是第5段。 – cha0site 2012-01-28 14:00:05

1

他在询问的区别。 当你在谈论不确定的行为你是对语言规范提供担保的水平 - 这是远离现实。 要了解真正的区别请这个片段(当然这是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); 
} 
9

有一个在他们是如何存储在存储器和寄存器两者之间没有区别,没有签名和未签名的int寄存器版本,没有与int一起存储的签名信息,差异只在执行数学运算时变得相关,数学运算的签名和未签名版本嵌入到CPU中,签名告诉编译器使用哪个版本。

+0

这个答案是最简单的 – 2016-06-17 20:37:41

1

这是一个非常简单的例子。二进制表示是它被提及但从未显示的关键。 如果0XFFFFFFF =机器码= 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(这里你可能想查看二进制加法) 我们必须一直带着这个。 1111 1111 1111 1111 1111 1111 1111 1110 = -1 所以我想在很短,我们可以说,不同的是一个允许负数其他没有,这是由于符号位或最左边的位或最重要的位。