找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

巢课
电巢直播8月计划
查看: 4|回复: 0
打印 上一主题 下一主题

[硬件] 单片机C语言易错知识点经验笔记

[复制链接]

551

主题

1470

帖子

3万

积分

EDA365管理团队

Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

积分
39487
跳转到指定楼层
1#
发表于 2019-9-27 15:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您!

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

x
今天写这一篇文章并不是因为已经想好了一篇文章才写下来,而是我要将这一篇文章作为一个长期的笔记来写,我会一直更新。在进行单片机开发时,经常都会出现一些很不起眼的问题,这些问题其实都是很基础的c语言知识点,是一些小细节。但是正是因为很基础,又都是小细节,所以我们往往容易忽视它们。结果有时候我们会花很长的时间纠结一个问题,迟迟找不到问题的所在。当发现原因竟然是这么的简单和不起眼时,我想不单是我,大家都会感到痛不欲生。笔者今天又碰到了这样的问题,实在忍不住了。因为这些问题都是小的知识点,考虑到之前也遇到好多这种问题,于是决定每次遇到问题就记录下来,时刻提醒自己。/ z6 h( k3 o+ X3 R; G
, a' b1 ~% _/ P
8 J/ f# w0 d4 I
1. !和 ~ 不一样; R; l0 o0 I2 L' B; ~+ Z/ l
9 S4 G3 a  u9 R7 W: ~9 y; a$ U) K

- w+ h# ^; m8 E( n  c; R! 是逻辑非符号,~ 是位取反符号。' B5 O# w3 I9 m+ L# T1 [( N
对IO口某个管脚赋值时不要错用 !,如
. \( A. a" K8 o$ N0 C- i3 X- r
* |1 G& S, e/ Z2 m$ `, {& }2 s+ T9 \9 a; r6 e

/ U9 z; u7 d9 a" ^* j2.<<和>>的优先级低于+、-
8 p5 m. O: D2 H/ @/ N( Q0 _
; Q6 _4 Z1 p- U; k0 \5 z" |8 d2 `/ ~: M7 E9 C
( i% y* G) X1 g
比如要实现c=x*2+1,没有加括号会出错
: r6 s- K  u: i% c
+ W4 w4 V5 \8 i  u( l9 z7 I; u4 B0 ^: z4 C# A& J/ A! G

$ y5 r* I$ W" [6 m3.移位要防止溢出
( u( [: X7 s2 u  t) ^$ u/ S& c5 R/ M# L# ~2 l
3 _& v& X$ I, _! v2 p$ n$ p6 P
其实用移位代替乘除法是个不错的方法,笔者很喜欢拿到一段代码后用移位代替乘除法来进行优化。不过有时候却会出现问题,比如溢出问题。当很明显可能溢出的话我们是会注意的,比如
2 E) J' K8 ]5 P  [0 c9 J; N
: M1 F) q$ i/ ~# E& ^/ l但是有时候这个问题是不明显的,比如当移位出现在数组索引或函数参数时,有段用液晶显示字符的代码如下
' n7 D, u' E# |3 o% m) Y% z# ^9 ]4 g) p* S4 ?( n
我们可以用左移运算来代替乘法进行优化,如- a' S0 Z& c3 \/ @9 O& _5 ?

, G' V% z1 f$ a& k; j8 `这本是一个好方法,但是事实上上面的代码是错的。当执行c<<4时,因为没有明显的赋值过程,我们可能认为没问题,而事实上c的高位已经丢失了,所以得到错误的结果。一个可行的做法是先进行强制转换,如
/ H3 x: R8 v- @7 M( K1 v0 M+ s+ w
  s, j' G: A0 U
' _# i& N5 Y& W* g& g
4.无符号数和有符号数混合运算都会被强制转换为无符号数运算
  O3 t5 I" C% X4 J0 `1 H3 h+ U* G( D! \; @) [* w) C/ v1 ]

; S, o" l$ a& S' G2 V0 m7 ]6 ^当一个有符号数和一个无符号数进行算术运算时,系统会自动将有符号数强制转换为无符号数再进行运算(即使你使用有符号数强制类型转换),如下面两种写法的运输结果是一样的+ M, {$ r! [& b( g5 L
: C* Q5 Y/ ~( ]( H: v% E3 f& ]
0 B" @  q: a- ^9 _" \; a& ]$ L
; ?" e" y! b3 L+ \& Q7 Y
' Q0 H4 M9 f8 g& ]' S8 {- r8 O
5.局部变量要初始化8 h# H8 G3 o: T: [" z3 v. c

) t7 d7 c1 s$ Y2 b, f% u' _+ x/ y# E# @7 F# c% J5 ]1 C
局部变量没有初始化的话,因为单片机每次为他分配的是同一个内存区域,当你在函数中是这么使用局部变量时,就可能出问题:; y7 X4 w" k8 D* }( t+ Y

+ T- l& @5 Q6 U7 O; H) ?; R如果第一次调用fun时,a传递的值为0,那么flag = 0x01;执行if(flag&0x01)后面的代码。以后再调用fun时,即使a不为0,但flag依然使用之前的内存区域,所以其值一直为0x01,一直执行的是if后面的代码,而不是else后面的。
0 I9 h; C2 n2 A  E+ Y: X, S! Z+ K9 ^, K5 c; u9 W/ A! }- T, b

1 i) Q! K6 d8 Q' |5 e如果要避免这个错误,平时要养成对局部变量初始化的习惯。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 支持!支持! 反对!反对!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

巢课

技术风云榜

关于我们|手机版|EDA365 ( 粤ICP备18020198号 )

GMT+8, 2025-4-7 07:27 , Processed in 0.060331 second(s), 33 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表