在 c 奇怪的行为中添加两个数字
Add two number in c strange behaviour
我正在读这个 Why is the sum of two large integers a negative number in the C language?。然后我尝试了以下代码:
int main() {
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u",s);
return 0;
}
输出:4294967294
1)它如何计算总和(s)?我对 link 中给出的解释感到有点困惑。
当我将 x
和 y
的值增加到超出 unsigned int
范围的程度时,结果似乎总是在 unsigned int 范围内。事实上,结果似乎一直在下降。
它确实给出了以下错误。
sample.c:7:9: warning: large integer implicitly truncated to unsigned type [-Woverflow]
2 ) 我可以暴力破解这个程序,以便每当 x
和 y
的值超过 unsigned int 范围程序就会抛出错误。
C 标准针对无符号整数溢出定义了明确的行为。发生这种情况时,数学结果将以最大允许值 + 1 为模截断。通俗地说,这意味着值环绕。
在添加 4294967295 和 4294967295 的情况下,这种环绕行为导致 4294967294。
抛出错误将违反标准。
1 ) How does it calculate sum (s)?
参见 好的答案。
2 ) Can I brute force this program so that whenever value of x and y exceeds unsigned int range program throws an error.
代码可以使用 unsigned
数学轻松检测数学溢出。如果总和小于加法的操作数,则会发生数学溢出。仅针对 x
或 y
之一进行测试就足够了。
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u\n",s);
if (s < x) puts("Math overflow");
// or
if (s < y) puts("Math overflow");
return 0;
对于 signed int
测试,请参阅 Test if arithmetic operation will cause undefined behavior
在你的情况下 unsigned int
是 32 位,4294967295 + 4294967295 == 8589934590 它有一个 33 位二进制值:
1 1111 1111 1111 1111 1111 1111 1111 1110
^
Carry bit
进位丢失,因为表示只有32位,结果值:
1111 1111 1111 1111 1111 1111 1111 1110 = 4294967294 decimal
您必须在溢出发生之前检测到溢出,然后将结果存储在更大的类型中并测试其值。
if( UINT_MAX - x < y )
{
puts("Math overflow") ;
}
else
{
s = x + y ;
printf( "%u\n", s ) ;
}
或:
unsigned long long s = x + y ;
if( s > UINT_MAX )
{
puts("Math overflow") ;
}
else
{
printf( "%u\n", (unsigned int)s ) ;
}
Most modern computers store memory in units of 8 bits, called a "byte"
(also called an "octet"). Arithmetic in such computers can be done in
bytes, but is more often done in larger units called "(short)
integers" (16 bits), "long integers" (32 bits) or "double integers"
(64 bits). Short integers can be used to store numbers between 0 and
216 - 1, or 65,535. Long integers can be used to store numbers between
0 and 232 - 1, or 4,294,967,295. and double integers can be used to
store numbers between 0 and 264 - 1, or 18,446,744,073,709,551,615.
(Check these!)
[...]
When a computer performs an unsigned integer arithmetic operation,
there are three possible problems which can occur:
if the result is too large to fit into the number of bits assigned to
it, an "overflow" is said to have occurred. For example if the result
of an operation using 16 bit integers is larger than 65,535, an
overflow results.
in the division of two integers, if the result is not itself an
integer, a "truncation" is said to have occurred: 10 divided by 3 is
truncated to 3, and the extra 1/3 is lost. This is not a problem, of
course, if the programmer's intention was to ignore the remainder!
any division by zero is an error, since division by zero is not
possible in the context of arithmetic.
[原来的重点已删除;已强调。]
我正在读这个 Why is the sum of two large integers a negative number in the C language?。然后我尝试了以下代码:
int main() {
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u",s);
return 0;
}
输出:4294967294
1)它如何计算总和(s)?我对 link 中给出的解释感到有点困惑。
当我将 x
和 y
的值增加到超出 unsigned int
范围的程度时,结果似乎总是在 unsigned int 范围内。事实上,结果似乎一直在下降。
它确实给出了以下错误。
sample.c:7:9: warning: large integer implicitly truncated to unsigned type [-Woverflow]
2 ) 我可以暴力破解这个程序,以便每当 x
和 y
的值超过 unsigned int 范围程序就会抛出错误。
C 标准针对无符号整数溢出定义了明确的行为。发生这种情况时,数学结果将以最大允许值 + 1 为模截断。通俗地说,这意味着值环绕。
在添加 4294967295 和 4294967295 的情况下,这种环绕行为导致 4294967294。
抛出错误将违反标准。
1 ) How does it calculate sum (s)?
参见
2 ) Can I brute force this program so that whenever value of x and y exceeds unsigned int range program throws an error.
代码可以使用 unsigned
数学轻松检测数学溢出。如果总和小于加法的操作数,则会发生数学溢出。仅针对 x
或 y
之一进行测试就足够了。
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u\n",s);
if (s < x) puts("Math overflow");
// or
if (s < y) puts("Math overflow");
return 0;
对于 signed int
测试,请参阅 Test if arithmetic operation will cause undefined behavior
在你的情况下 unsigned int
是 32 位,4294967295 + 4294967295 == 8589934590 它有一个 33 位二进制值:
1 1111 1111 1111 1111 1111 1111 1111 1110
^
Carry bit
进位丢失,因为表示只有32位,结果值:
1111 1111 1111 1111 1111 1111 1111 1110 = 4294967294 decimal
您必须在溢出发生之前检测到溢出,然后将结果存储在更大的类型中并测试其值。
if( UINT_MAX - x < y )
{
puts("Math overflow") ;
}
else
{
s = x + y ;
printf( "%u\n", s ) ;
}
或:
unsigned long long s = x + y ;
if( s > UINT_MAX )
{
puts("Math overflow") ;
}
else
{
printf( "%u\n", (unsigned int)s ) ;
}
Most modern computers store memory in units of 8 bits, called a "byte" (also called an "octet"). Arithmetic in such computers can be done in bytes, but is more often done in larger units called "(short) integers" (16 bits), "long integers" (32 bits) or "double integers" (64 bits). Short integers can be used to store numbers between 0 and 216 - 1, or 65,535. Long integers can be used to store numbers between 0 and 232 - 1, or 4,294,967,295. and double integers can be used to store numbers between 0 and 264 - 1, or 18,446,744,073,709,551,615. (Check these!)
[...]
When a computer performs an unsigned integer arithmetic operation, there are three possible problems which can occur:
if the result is too large to fit into the number of bits assigned to it, an "overflow" is said to have occurred. For example if the result of an operation using 16 bit integers is larger than 65,535, an overflow results.
in the division of two integers, if the result is not itself an integer, a "truncation" is said to have occurred: 10 divided by 3 is truncated to 3, and the extra 1/3 is lost. This is not a problem, of course, if the programmer's intention was to ignore the remainder!
any division by zero is an error, since division by zero is not possible in the context of arithmetic.
[原来的重点已删除;已强调。]