c语言数据类型定义错误导致的数据溢出或者死循环

数据溢出问题

#include 

/*
数据溢出
*/

int main()
{
  char i;    // 数据表示范围[-128,127]   0xf0 ~ 0x7f
  for(i=0;i<130;i++)   //  
  {
    printf("%d ",i);
  }
  return 0;
}

/*
编译运行上面的程序,你会发现程序陷入了死循环,一直在不断打印。当我们给一个变量赋一个超出其能表示范围的数时,就会发生
数据溢出,如上面的示例代码所示,导致程序运行出现异常。

对于有符号数,当发生数据溢出时,由于C语言的语法宽松性,不对数据类型做安全性检查,因此也不会触发异常,但是会产生一个
未定义行为。什么是未定义行为呢?通俗点理解,就是遇到这种情况时,C语言标准也没有规定该如何操作,各家编译器在处理这种情况时也就没有了参考标准,各自按照自己的方式处理,编译器都不算错误。这也导致了当有符号数发生溢出时,运行结果是不确定的,在不同的编译器环境下编译运行,结果可能不一样。
*/
#include 

/*
数据溢出(无符号)
*/

int main()
{
    unsigned char a=255;  // unsigned char的数据表示范围为[0,255]
    printf("%u\n",a);
    a++;
    printf("%u\n",a);
    return 0;
}

一般来讲,无符号数溢出时会进行取模运算,继续“周期轮回”

例如,一个unsigned char类型的数据,它能表示的数据范围为[0,255],当其循环到255最大值时继续加1,这个数就变成了0,开始新的一轮循环,周而复始。

#include 

/*
数据溢出
*/

int main()
{
    signed char a=127;  // unsigned char的数据表示范围为[0,255]
    printf("%d\n",a);
    a++;
    printf("%d\n",a);
    return 0;
}
/*
大家可以尝试在不同的编译器环境下编译运行上面的程序,你会发现大部分结果都是-128,也就是说大部分编译器都默认采用了与无符号数一样的轮回处理
*/
int main()
{
   unsigned char a=0;  // a的取值[0,255]
   printf("a=%d\n",a);
   a--;  // 周期轮回,a变成255
   printf("a=%d\n",a);
   return 0;
}

在这里插入图片描述

int print_star( unsigned int len)
{
    int i=1;
    while(len-- >=0)
    {
       if(i++%20==0)
           printf("\n");
       printf("*");
    }
    printf("\n");
    return 0;
}

以上程序的设计存在问题,如果我们在调用该函数时给它传递一个实参-1,你会发现该程序将陷入死循环。这是因为 l e n len len是unsigned int类型,unsigned int类型在递减的时候存在数据溢出的问题,当减到-1时数据发生溢出, l e n len len的值变成 2 32 − 1 {2}^{32}-1 2321,所以在 l e n len len递减的情况下, l e n ≥ 0 len\ge0 len0

为了防止这种问题发生,我们有两种解决方法:可以将函数的参数类型设置为signed int,或者在print_star()函数中对传进来的实
参进行判断(如代码中注销的示例代码),预防由于隐式类型自动转换而使代码的程序逻辑发生不确定的变化。

如何防范数据溢出?

对于有符号数的相加,方法其实很简单,我们先看看两个有符号数相加的情况。如果两个正数相加的和小于0,说明运算过程中发生了数据溢出。同理,如果两个负数相加的和大于0,也说明数据发生了溢出。

#include 

/*
数据溢出
*/

int main()
{
   char a =127;
   char b=30;
   char c=a+b;
   if(c<0)
   {
      printf("data overflow!!\n");
   }
   else{
      printf("%d\n",c);
   }
   return 0;
}

在这里插入图片描述
对于无符号数的相加,如果两个数的和小于其中任何一个加数,此时我们也可以判断数据在计算过程中发生了溢出现象。

#include 

/*
数据溢出
*/

int main()
{
   unsigned char a =255;
   unsigned char b=30;
   unsigned char c=a+b;
   if(c<a  || c<b)
   {
       printf("data overflow!!\n");
   }
   else{
       printf("%d\n",c);
   }
   return 0;
}

在这里插入图片描述

你可能感兴趣的:(嵌入式c语言高级编程,c语言,开发语言)