整数溢出问题

时间:2009-08-20 15:02:34

标签: c

请解释以下段落。

“接下来的问题是我们是否可以在不失去精度的情况下为变量赋值。如果我们只是在加法或减法期间检查溢出是不够的,因为有人可能会添加1到-5并分配结果到一个unsigned int。那么实际的加法不会溢出,但结果仍然不合适。“

当我加1到-5时,我没有任何理由担心。答案是应该是-4。 那么结果不合适的问题是什么? 你可以在这里找到我要去的完整文章:

http://www.fefe.de/intof.html

8 个答案:

答案 0 :(得分:5)

尝试将其分配给unsigned int,而不是int。

术语unsigned int是关键 - 默认情况下,int数据类型将包含负数和正数;但是,无符号整数总是为正。它们提供了这个选项,因为从技术上来说,uints可以比常规的有符号整数保持更大的正值,因为它们不需要用一点来跟踪它的负面还是正面。

请参阅:

Signed versus Unsigned Integers

答案 1 :(得分:5)

在32位字中的-4的二进制表示如下(十六进制表示法)

0xfffffffc

当解释为无符号整数时,此位模式表示数字 2 ** 32-4 或18446744073709551612.我不确定我会称这种现象“溢出”,但是常见错误将一个小的负整数分配给一个无符号类型的变量,最后得到一个非常大的正整数。

这个技巧实际上被用于边界检查:如果你有一个有符号整数i,并想知道它是否在0< = i< n,你可以测试

if ((unsigned)i < n) { ... }

使用一个比较而不是两个来给出答案。演员到无人签名没有运行时成本;它只是告诉编译器生成无符号比较而不是签名比较。

答案 2 :(得分:2)

问题是你在 unsigned int中存储了-4。无符号整数只能包含零和正值。如果你将-4分配给一个,你实际上最终得到一个非常大的正数(实际值取决于你使用的int的宽度)。

答案 3 :(得分:2)

问题在于unsigned int等存储空间的大小只能容纳这么多。使用1和-5无关紧要,但使用1和-500000000可能会导致混乱的结果。此外,unsigned存储会将存储在其中的任何内容解释为正数,因此您无法在unsigned变量中添加负值。

需要注意的两件大事:
1.操作本身溢出:1 + -500000000
2.投射问题:(unsigned int)(1 + -500)

答案 4 :(得分:0)

根据定义 ,号码-4无法在unsigned int中表示。 -4是有符号整数。任何负数也是如此。

当您为unsigned int分配负整数时,该数字的实际位数不会更改,但它们仅以表示不同。由于整数在二进制(two's complement)中的表示方式,你会得到一些可笑的大数。

在二进制补码中,-4表示为0xfffffffc。当0xfffffffc表示为unsigned int时,您将获得数字4,294,967,292

答案 5 :(得分:0)

无符号变量(如unsigned int)不能保存负值。因此,将1 - 5分配给unsigned int将不会给你-4。我不确定它会给你什么,它可能是特定于编译器的。

答案 6 :(得分:0)

一些代码:

signed int first, second;
unsigned int result;

first = obtain(); // happens to be 1
second = obtain(); // happens to be -5
result = first + second; // unexpected result here - very large number - and it's too late to check that there's a problem

假设您从键盘获取了这些值。您需要在添加之前检查结果是否可以用unsigned int表示。这就是文章所说的内容。

答案 7 :(得分:0)

你必须记住,从根本上说你正在使用比特。因此,您可以将值-4分配给无符号整数,这会将一系列位放入该内存位置。在某些情况下,这些位可以解释为-4 。一个这样的情况是显而易见的:你已告诉编译器/系统该存储器位置中的位应被解释为两个符号签名号。因此,如果你做printf(“%s”,i)prtinf发挥其魔力并将两个恭维数转换为幅度和符号。幅度为4,符号为负,因此显示“-4”。

但是,如果您告诉编译器该内存位置的数据未签名,则位不会更改,而是其解释。因此,当您进行添加时,将结果存储在无符号整数存储器位置,然后在结果上调用printf,它不会在寻找符号,因为根据定义它始终是正数。它计算幅度并打印出来。幅度将关闭,因为符号信息仍然以比特编码,但它被视为幅度信息。