for循环中if语句的一个诡异的问题

无名D小兵 2021-02-27 10:17:25
下面是我写的一段代码,旨在将数组nums中的元素整合成一个整数,在整合过程中检测是否超过int类型的数值范围,一旦超过就返回0
int main(void)
{
int x=0;
int nums[11]={0,3,2,1};
int i=4,j;
int a=nums[0];

for (j = 1; j < i; j++)
{
if (a == 0)
{
//if(x*10<-2147483648 || x*10>2147483647 || x*10+nums[j]<-2147483648 || x*10+nums[j]>2147483647)
if (x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647)
//return 0;
return 0;
}
//else if (nums[0] == 1) //对负数的处理
if (a == 1) //对负数的处理
{
//if(0-(x*10)<-2147483648 || 0-(x*10)>2147483647 || 0-(x*10+nums[j])<-2147483648 || 0-(x*10+nums[j])>2147483647)
if (0 - (x * 10) < -2147483648 || 0 - (x * 10 + nums[j]) < -2147483648)
return 0;
}
//if(a==0)
//{
// if (x * 10 > 2147483647L || x * 10 + nums[j] > 2147483647L)
// return 0;
//}
x = x * 10 + nums[j];
}

printf("%d\n",x);
return 0;
}

一个诡异的问题是,程序会跳过for循环里的两条if语句,直接执行循环里的最后一条语句。这是怎么回事?
求大神解答
...全文
229 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
forever74 2021-02-28
  • 打赏
  • 举报
回复
回过头看,编译器优化掉一些分支很正常,你要是实在闹心可以先试试 -O0 或者在两个if中间printf一下,那就不算无用分支了。
真相重于对错 2021-02-28
  • 打赏
  • 举报
回复
引用 13 楼 无名D小兵 的回复:
[quote=引用 10 楼 真相重于对错 的回复:] if (a == 0)//这句话执行了 { //if(x*10<-2147483648 || x*10>2147483647 || x*10+nums[j]<-2147483648 || x*10+nums[j]>2147483647) if (x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647)//这句判断永为假 //return 0; return 0;//因此这句话不会得到执行的机会 } 自己打断点,或者加入输出语句,或者单步执行,就应该清楚了
有做,就是单步执行过程中跳过了这一条语句才奇怪的。[/quote]

        if (a == 0)
        {
            printf("a==0\n");//这里加一句输出不就清楚了?
            //if(x*10<-2147483648 || x*10>2147483647 || x*10+nums[j]<-2147483648 || x*10+nums[j]>2147483647)
            if (x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647)
                //return 0;
                return 0;
        }
无名D小兵 2021-02-28
  • 打赏
  • 举报
回复
引用 10 楼 真相重于对错 的回复:
if (a == 0)//这句话执行了 { //if(x*10<-2147483648 || x*10>2147483647 || x*10+nums[j]<-2147483648 || x*10+nums[j]>2147483647) if (x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647)//这句判断永为假 //return 0; return 0;//因此这句话不会得到执行的机会 } 自己打断点,或者加入输出语句,或者单步执行,就应该清楚了
有做,就是单步执行过程中跳过了这一条语句才奇怪的。
forever74 2021-02-28
  • 打赏
  • 举报
回复
难道gcc有这么聪明,懂得删除无用分支? 好吧,真的有这么聪明的编译器。
无名D小兵 2021-02-28
  • 打赏
  • 举报
回复
引用 9 楼 forever74 的回复:
[quote=引用 8 楼 无名D小兵 的回复:][quote=引用 3 楼 真相重于对错 的回复:]a=num[0],也就是0,后边也没有修改过a ,所以下边a==1,本程序不会执行。
我好奇的是,连a是否等于0都没有判断[/quote] 何以见得呢?[/quote] 用GDB调试时发现的
无名D小兵 2021-02-28
  • 打赏
  • 举报
回复
引用 15 楼 forever74 的回复:
回过头看,编译器优化掉一些分支很正常,你要是实在闹心可以先试试 -O0 或者在两个if中间printf一下,那就不算无用分支了。
好的,谢谢。
真相重于对错 2021-02-27
  • 打赏
  • 举报
回复
a=num[0],也就是0,后边也没有修改过a ,所以下边a==1,本程序不会执行。
真相重于对错 2021-02-27
  • 打赏
  • 举报
回复
上边有误,应永远为假
真相重于对错 2021-02-27
  • 打赏
  • 举报
回复
x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647 这样的语句永远为真,因为int 永远不会大于INT32_MAX ,如果计算结果大于了INT32_MAX,则会回卷。
真相重于对错 2021-02-27
  • 打赏
  • 举报
回复
if (a == 0)//这句话执行了 { //if(x*10<-2147483648 || x*10>2147483647 || x*10+nums[j]<-2147483648 || x*10+nums[j]>2147483647) if (x * 10 > 2147483647 || x * 10 + nums[j] > 2147483647)//这句判断永为假 //return 0; return 0;//因此这句话不会得到执行的机会 } 自己打断点,或者加入输出语句,或者单步执行,就应该清楚了
forever74 2021-02-27
  • 打赏
  • 举报
回复
引用 8 楼 无名D小兵 的回复:
[quote=引用 3 楼 真相重于对错 的回复:]a=num[0],也就是0,后边也没有修改过a ,所以下边a==1,本程序不会执行。
我好奇的是,连a是否等于0都没有判断[/quote] 何以见得呢?
无名D小兵 2021-02-27
  • 打赏
  • 举报
回复
引用 3 楼 真相重于对错 的回复:
a=num[0],也就是0,后边也没有修改过a ,所以下边a==1,本程序不会执行。
我好奇的是,连a是否等于0都没有判断
[PE]经典八炮 2021-02-27
  • 打赏
  • 举报
回复
或者以字符串的形式判断
[PE]经典八炮 2021-02-27
  • 打赏
  • 举报
回复
输入的时候,如果超出int的范围,会回卷。你可以用long long类型,如果没超出范围,再转为int
forever74 2021-02-27
  • 打赏
  • 举报
回复
计算机的数学不是人类数学,它只是一个粗糙的近似。 这就是现行的计算机体系结构不能诞生真正的人工智能的哲学层面的理由。
forever74 2021-02-27
  • 打赏
  • 举报
回复
这有啥诡异的,就好象 你取得了自己所在位置的地球经纬度,然后写了个if 说如果在东经180度的东边,或者在西经180度的西边,或者北纬90度北边,或者南纬90度南边,那就输出个出错信息。 这不就是废话么?自然的就废掉了。 道理一样一样的。

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧