今天写这一篇文章并不是因为已经想好了一篇文章才写下来,而是我要将这一篇文章作为一个长期的笔记来写,我会一直更新。在进行单片机开发时,经常都会出现一些很不起眼的问题,这些问题其实都是很基础的c语言知识点,是一些小细节。但是正是因为很基础,又都是小细节,所以我们往往容易忽视它们。结果有时候我们会花很长的时间纠结一个问题,迟迟找不到问题的所在。当发现原因竟然是这么的简单和不起眼时,我想不单是我,大家都会感到痛不欲生。笔者今天又碰到了这样的问题,实在忍不住了。因为这些问题都是小的知识点,考虑到之前也遇到好多这种问题,于是决定每次遇到问题就记录下来,时刻提醒自己。

1. !和 ~ 不一样

! 是逻辑非符号,~ 是位取反符号。

对IO口某个管脚赋值时不要错用 !,如

LCD_CS_n_DR &= !LCD_CD_n_MASK;	//错误
LCD_CS_n_DR &= ~LCD_CD_n_MASK; //正确

2.<<和>>的优先级低于+、-

比如要实现c=x*2+1,没有加括号会出错

c = x<<1+ 1;  	//错误,c=x*(1+1)
c = (x<<1) + 1; //正确,c=x*2+1

3.移位要防止溢出

其实用移位代替乘除法是个不错的方法,笔者很喜欢拿到一段代码后用移位代替乘除法来进行优化。不过有时候却会出现问题,比如溢出问题。当很明显可能溢出的话我们是会注意的,比如

char m = c<<4;	//c为char型,可能溢出

但是有时候这个问题是不明显的,比如当移位出现在数组索引或函数参数时,有段用液晶显示字符的代码如下

char m = Font8x16[c*16+1]; //c为字符,寻找c的点阵字库

我们可以用左移运算来代替乘法进行优化,如

char m = Font8x16[(c<<4)+1];	//c为字符,寻找c的点阵字库

这本是一个好方法,但是事实上上面的代码是错的。当执行c<<4时,因为没有明显的赋值过程,我们可能认为没问题,而事实上c的高位已经丢失了,所以得到错误的结果。一个可行的做法是先进行强制转换,如

char m = Font8x16[(uint16)c<<4)+1];	//c为字符,寻找c的点阵字库

4.无符号数和有符号数混合运算都会被强制转换为无符号数运算

当一个有符号数和一个无符号数进行算术运算时,系统会自动将有符号数强制转换为无符号数再进行运算(即使你使用有符号数强制类型转换),如下面两种写法的运输结果是一样的

char a = (unsigned char)b / (signed char)c;
char a = (unsigned char)b / (unsigned char)c;

如果a=

5.局部变量要初始化

局部变量没有初始化的话,因为单片机每次为他分配的是同一个内存区域,当你在函数中是这么使用局部变量时,就可能出问题:

void fun(char a)
{
if(a==0)
flag |= 1;
...
if(flag & 0x01)
...;
else
...;
}

如果第一次调用fun时,a传递的值为0,那么flag = 0x01;执行if(flag&0x01)后面的代码。以后再调用fun时,即使a不为0,但flag依然使用之前的内存区域,所以其值一直为0x01,一直执行的是if后面的代码,而不是else后面的。

如果要避免这个错误,平时要养成对局部变量初始化的习惯。

[置顶] 单片机C语言易错知识点经验笔记的更多相关文章

  1. [C语言]易错知识点、小知识点复习(1)

    1. 计算机只能识别由0和1组成的二进制指令,需要将用高级语言(如C.C++)编写的源程序(.c..cpp)编译成二进制目标文件(.obj).一个程序可以根据需要写在不同的文件里,编译是以文件为单位进 ...

  2. JavaScript易错知识点整理

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  3. JavaScript 易错知识点整理

    本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES ...

  4. JavaScript易错知识点整理[转]

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  5. JS易错知识点

    JAVASCRIPT易错知识点整理 前言 本文是学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由 ...

  6. C语言易错点

    C语言易错点 1.每个C语言程序中main函数是有且只有一个的. 2.算法可以没有输入,但必须要有输出. 3.在函数中不可以再定义函数. 4.break可用于循环结构和switch语句. 5.brea ...

  7. Java易错知识点(1) - 关于ArrayList移除元素后剩下的元素会立即重排

    帮一个网友解答问题时,发现这样一个易错知识点,现总结如下: 1.易错点: ArrayList移除元素后,剩下的元素会立即重排,他的 size() 也会立即减小,在循环过程中容易出错.(拓展:延伸到所有 ...

  8. JavaScript易错知识点

    JavaScript易错知识点整理1.变量作用域上方的函数作用域中声明并赋值了a,且在console之上,所以遵循就近原则输出a等于2. 上方的函数作用域中虽然声明并赋值了a,但位于console之下 ...

  9. iOS中 项目开发易错知识点总结

    点击return取消textView 的响应者 - (BOOL)textFieldShouldReturn:(UITextField *)textField { [_contactTextFiled  ...

随机推荐

  1. CornerStone 破解 最简单的破解方法

    方法一:最近在用cornerstone这个svn的软件感觉非常不错,但是竟然忘了破解,以至于到了14天试用期的最后一天才开始破解, 其实方法很简单,就是修高试用期的天数,找到plist文件把14天改为 ...

  2. CCArray(转)

    http://blog.csdn.net/passtome/article/details/7966451 CCArray也是cocos2d-x自己写的类.它相当于是objc的NSArray.在coc ...

  3. CentOS下配置SMTP

    在服务器上配置一个SMTP邮件服务可能是在日常工作中经常会遇到的需要,比如在做一些简单测试的时候. 配置步骤无比简单,废话不说: 1,yum -y install mail 2,编辑/etc/mail ...

  4. 自定义控件 环形进度条 ProgressBar

    使用 public class MainActivity extends Activity implements OnComompleteListener {     private int num  ...

  5. JQuery中常用的 属性选择器

    jQuery中使用$()作为选择符极大提高工作效率以及方便快捷;一些常用属性的选择器由以下几种 1) $('#id') id选择器 2) $('.class') css选择器,class类名 3) $ ...

  6. asp.net 面试基础题

    WebSite和WebApplication的区别1)当改变后台代码时,WebApplication需重启浏览器或者重新生成解决方案,而WebSite则不用:2)WebSite没有Solution,没 ...

  7. 工厂方法模式(java 设计模式)

    1.工厂方法模式的定义 工厂方法模式使用的频率非常高, 在我们日常的开发中总能见到它的身影. 其定义为:Define an interface for creating an object,but l ...

  8. Android view 小总结

    android 中, view 的绘制包含三步: 1. onMeasure(), 对view进行测量: 2. onLayout(),对view进行布局: 3.onDraw(),对view进行绘制. v ...

  9. 学习okhttp wiki--HTTPS

    HTTPS OkHttp尝试平衡两个相互竞争的要素: 连通性(Connectivity):连接到尽可能多的服务器.这包括运行最新版本 boringssl 的服务器和不太过时的老版本 OpenSSL 的 ...

  10. 如何读懂SQL Server的事务日志

    简介 本文将介绍SQL Server的事务日志中记录了哪一些信息,如何来读懂这些事务日志中信息.首先介绍一个微软没有公开的函数fn_dblog,在文章的接下来的部分主要用到这个函数来读取事务日志. f ...