"int"和"unsigned int"之间的真正区别

Fab*_*cio 51 c

int:

32位int数据类型可以包含-2,147,483,648到2,147,483,647范围内的整数值.您也可以将此数据类型称为signed int或signed.

unsigned int:

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
Run Code Online (Sandbox Code Playgroud)

没有区别,噢我有点困惑.

cha*_*ite 46

呵呵.你在这里有一个隐式转换,因为你告诉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");
Run Code Online (Sandbox Code Playgroud)


cni*_*tar 24

是的,因为在您的情况下,他们使用相同的表示.

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

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


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

该标准指出了它 7.19.6.1-9

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

  • 真正的原因是他使用%u打印两者. (4认同)
  • 真正的原因是他通过将非类型匹配格式字符串传递给`printf`来调用未定义的行为**.我几乎想要删除所有正在跳过这个问题的答案,并指出关于表示的无关紧要的东西...... (3认同)

Nat*_*Day 18

它们如何存储在内存和寄存器中没有区别,没有有符号和无符号版本的int寄存器没有用int存储的签名信息,差异只在执行数学运算时变得相关,有内置于CPU中的数学运算的有符号和无符号版本,签名告诉编译器使用哪个版本.


pmg*_*pmg 7

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


当你调用UB时,任何事情都可能发生.

作业还可以; 第一行有一个隐式转换

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
Run Code Online (Sandbox Code Playgroud)

但是,打电话printf,不行

printf("%d, %d, %u, %u", x, y, x, y);
Run Code Online (Sandbox Code Playgroud)

这是UB失配的%说明符和参数的类型.
你的情况您指定2 int秒和2 unsigned int的顺序,提供1秒int,1 unsigned int,1 int,和1 unsigned int.


不要做UB!

  • -1,错了.这不是未定义的行为.查看C99第6.5.2.2节第6段. (3认同)

Raf*_*cki 5

的内部表示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
Run Code Online (Sandbox Code Playgroud)

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


pgr*_*ard 5

二进制表示是关键。示例:十六进制形式的无符号整数

 0XFFFFFFF = translates to = 1111 1111 1111 1111 1111 1111 1111 1111 
Run Code Online (Sandbox Code Playgroud)

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

0000 0000 0000 0000 0000 0000 0000 0011 = 3
Run Code Online (Sandbox Code Playgroud)

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

0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645
Run Code Online (Sandbox Code Playgroud)

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

1111 1111 1111 1111 1111 1111 1111 1111 = -1
Run Code Online (Sandbox Code Playgroud)

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