Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C INT_MAX在If语句中的行为不正确_C_If Statement_Int_Max - Fatal编程技术网

C INT_MAX在If语句中的行为不正确

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语句

我的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)时,它才起作用。为什么

#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;i
init_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 3
false
在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;