C INT_MAX在If语句中的行为不正确
我的C程序执行一个“turmrechung”(一个预定义的数字(“init_num”)乘以一个预定义的数字范围(在我的例子中,init_num*2*3*4*5*6*7*8*9,由变量“h”定义),然后再除以这些相同的数字,结果应该是“init_num”的初始值。我的任务是集成一种方法,以便在init_num的值大于INT_MAX(从limits.h开始)时停止计算。 但如果初始值“init_num”较大,则If语句始终为真,即使不是真,这会导致计算过程中的值大于INT_MAX 只有当我在if语句中将“INT_MAX”替换为比INT_MAX更小的数字(比如200000000)时,它才起作用。为什么C INT_MAX在If语句中的行为不正确,c,if-statement,int,max,C,If Statement,Int,Max,我的C程序执行一个“turmrechung”(一个预定义的数字(“init_num”)乘以一个预定义的数字范围(在我的例子中,init_num*2*3*4*5*6*7*8*9,由变量“h”定义),然后再除以这些相同的数字,结果应该是“init_num”的初始值。我的任务是集成一种方法,以便在init_num的值大于INT_MAX(从limits.h开始)时停止计算。 但如果初始值“init_num”较大,则If语句始终为真,即使不是真,这会导致计算过程中的值大于INT_MAX 只有当我在if语句
#include <limits.h>
#include <stdio.h>
int main() {
int init_num = 1000000;
int h = 9;
for (int i = 2; i < h+1; ++i)
{
if (init_num * i < INT_MAX)
{
printf("%10i %s %i\n", init_num, "*", i);
init_num *= i;
}
else
{
printf("%s\n","An overflow has occurred!");
break;
}
}
for (int i = 2; i < h+1; ++i)
{
printf("%10i %s %i\n", init_num, ":", i);
init_num /= i;
}
printf("%10i\n", init_num);
}
#包括
#包括
int main(){
int init_num=1000000;
int h=9;
对于(int i=2;iinit_num*i
只有在INT_num*i
为INT_MAX
时才会为0。这不太可能。请注意,有符号整数溢出在C中是未定义的行为,因此在这里要特别小心
在特定情况下,您可以将语句重写为init\u num
。但请注意整数除法会截断
init_num * int
结果为int
,但根据定义不能超过最大可能int
(int\u MAX
)
因此,通过替换,为“大于”int的计算提供“空间”
if (init_num * i < INT_MAX)
if(init_num*i
与
if((长)初始值*i<(长)整数最大值)
转换为long
将导致long
结果
(上述方法假设long
比int
更宽)问题是有符号整数溢出是未定义的行为。请关注“未定义”部分并思考一下。简单地说:在所有情况下都要避免
为了避免这种情况,您可以使用一种更宽的类型,它需要保存乘法的结果,然后测试:
// ensure the type we use for cast is large enough
_Static_assert(LLONG_MAX > INT_MAX, "LLONG too small.");
if ( (long long)init_num * i < (long long)INT_MAX )
//确保用于强制转换的类型足够大
_静态断言(LLONG_MAX>INT_MAX,“LLONG太小”);
if((长-长)初始数量*i<(长-长)整数最大值)
这显然不起作用,因为您已经达到极限(即使用最大的数据类型)。因此您必须提前检查:
if ( init_num < (INT_MAX / i) ) {
init_num *= i;
if(初始数量<(整数最大值/i)){
init_num*=i;
虽然由于额外的除法而更耗时,但这通常是更好的方法,因为它不需要更大的数据类型(乘法也可能更昂贵)“ <代码> INTXMAX是一个<代码> int <代码>的最大值。考虑一下。你应该做一些关于溢出如何实际工作的阅读。提示:一个整数有一个符号。当你的程序明显地需要存储尽可能大的无符号数字时,你也应该考虑为什么你要使用带符号的数字。@关于它们,除了学习有符号整数溢出调用未定义的行为之外?除此之外,没有什么有趣的事情要知道。整数乘以整数总是整数!整数总是比整数小或相等,就像整数最大值一样。在你的例子中,只有当init_num*i是整数最大值时,init_num*ifalse
更改为0漂亮吗?我们在C中。@Bathsheba是的,我会这样做。@Bathsheba即使C
没有布尔数据类型,它仍然有布尔的概念。条件要么为false,要么为true。@Bathsheba在C中,false
扩展为整数常量0”C11§7.18 3false
在C中是可以的。每个操作符<(小于),[…]如果指定的关系为真,则应产生1,如果为假,则产生0。结果的类型为int。
,因此,当表达式的结果为1
或0
时,说条件永远不会为假没有错。
boolena表达式产生真或假。使用0
作为标记或“false”作为逻辑术语,但“0”与false
be一样是错误的。通常情况下,您是错误的,因为任何溢出都是UB,这可能会产生任何结果,包括后台进程。
if ((long) init_num * i < (long) INT_MAX)
// ensure the type we use for cast is large enough
_Static_assert(LLONG_MAX > INT_MAX, "LLONG too small.");
if ( (long long)init_num * i < (long long)INT_MAX )
if ( init_num < (INT_MAX / i) ) {
init_num *= i;