[麦麦茶水间] 【每周分享】C语言中容易发生的几个常见错误

[复制链接]
 楼主| dffzh 发表于 2025-8-8 13:22 | 显示全部楼层 |阅读模式
本帖最后由 dffzh 于 2025-8-8 13:26 编辑

#申请原创#
@21小跑堂


在基于C语言的嵌入式产品开发中,我们会经常解决和修复一些Bug,甚至有时候会被疑难杂症整的脑壳疼,以为是什么高深莫测的问题,但是呢,有时候一些Bug分析到最后,一般都是由一些小问题导致的,这些小问题包括数据溢出,数组越界和指针未初始化等等,所以我就根据自己的一些经验和遇到的,讲解在C语言开发中比较容易发生的几个错误,包括错误产生的原因,举例说明及如何规避。
1. 忽略程序编译警告
在程序编译时,更多时候我们可能只关注错误errors,而容易忽略警告warnnings,哪怕警告有几十甚至上百个。其实,很多警告就是在提醒我们该处代码操作存在潜在问题,在特定情况下可能会造成程序错误。比如下面这个就是一个比较常见的警告信息:

大概意思就是此处应该用定义的枚举数据,但实际上用的可能是整型等数据类型。
如果你用的非枚举数据值是在已定义的枚举数据里面,是没有问题的,如果你用的值不在这个里面,你的程序会怎么执行?你有做入参检查吗?因此,对应这个警告,你就尽可能的直接使用枚举数据来调用,这肯定就不会错了,其实这个也算是编程习惯问题。类似的还有:


因此在程序开发时,尽量做到下面这样就完美了,可以帮你提前规避一些程序潜在问题:


2. 宏定义漏掉括号
我们使用#define定义宏时,除非必须要加括号才加,有时候我们可能不会刻意加上括号,也可能是忘记加了,结果程序运行出现异常,反查代码后才发现原来是漏掉括号导致的。比如下面的代码就是很经典的一个案例,目的是求x的平方值:
  1. #define SQUARE(x) x*x
  2. unsigned char a=1;
  3. printf("%d\r\n", SQUARE(a+1));
我们的想法肯定是求(a+1)*(a+1)=4,但实际结果为什么是3呢?

因为宏定义漏掉了括号,导致程序实际执行的是a+1*a+1=3;
因此最好的定义方式是:
  1. #define SQUARE(x) ((x)*(x))
即使用#define定义宏时,对每一个最小单位的操作数都加上括号,哪怕就一个数字也加上,养成良好的习惯:
  1. #define MAX (255)

3. 变量没有执行初始化操作
对于全局变量和局部变量,特别是局部变量,我们一定要加初始化操作,即声明好一个变量后,先完成对其的初始化操作。对于局部变量,如果不进行初始化,其默认值不一定是0,可能是其他的随机值,容易导致难以预测的结果,我们来看看下面的代码执行结果就知道了:


4. 使用==等号判断浮点数是否相等
因为浮点数在不同系统上呈现出来的精度是不一样的,我们不能像整型数据那样用==等号来判断两个浮点数是否相等,这样会导致比较结果错误,影响程序的运行逻辑,即不能按如下代码操作:
  1. float a = 0.11;
  2. float b = 0.11;
  3. if (a == b)
  4. {
  5.     printf("Equal\n");
  6. } else
  7. {
  8.     printf("Not Equal\n");
  9. }
而应该使用一个比较小的阈值THRESHOLD来间接判断两个浮点数是否相等,即按如下代码操作:
  1. #define THRESHOLD (0.000001)  //该值视系统和具体情况进行自定义修改
  2. float a = 0.11;
  3. float b = 0.11;
  4. if (fabs(a - b) < THRESHOLD)
  5. {
  6.     printf("Equal\n");
  7. } else
  8. {
  9.     printf("Not Equal\n");
  10. }

5. 使用数组对字符串的处理不正确
因为字符串用数组定义的话,是属于字符数组,我们很容易忽视结束符“\0”,从而导致访问越界,比如下面的代码编译时就直接报错了:

因为hello加上\0是6个字符,而数组大小是5,因此错误了。对于这种情况,可以用:
  1. char str[6] = "hello";  //在数组中具体指明长度
对应字符串较长的情况,我们总不能一个一个去数吧,那就可以按如下方式定义:
  1. char str[] = "hello, my name is C program!";  //数组长度空,在C语言中是允许的

6. 数组越界操作
数组是我们经常会使用到的一种数据结构,也是很容易出错的,主要原因是数组里定义的元素总数假设为MAX,此时我们实际可以访问的数组元素是从数组[0]~数组[MAX-1],而并非是数组[MAX],如果你误操作用上数组[MAX],就属于数组越界操作了,可能会导致程序崩溃等,如下代码即为越界操作的示例:
因此,对于数组操作,我们尽量定义一个数组长度的宏,通过使用这个宏可以规避不少误操作:
  1. #define  ARRAY_LENGTH_MAX  (5)
  2. int i=0;
  3. int arr[ARRAY_LENGTH_MAX] = {1, 2, 3, 4, 5};
  4. printf("%d\n", arr[ARRAY_LENGTH_MAX-1]);
  5. for(i=0; i<ARRAY_LENGTH_MAX; i++)
  6. {
  7.         printf("%d\n", arr[i]);
  8. }
以上通过实际代码讲解了C语言开发中经常遇见的几个错误以及如何规避和预防。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评论

[url=home.php?mod=space&uid=760190]@21小跑堂[/url] 管理员,你好,求原创审核哦!  发表于 2025-8-8 13:28
您需要登录后才可以回帖 登录 | 注册

本版积分规则

109

主题

1164

帖子

22

粉丝
快速回复 在线客服 返回列表 返回顶部