找回密码
 注册
关于网站域名变更的通知
查看: 367|回复: 2
打印 上一主题 下一主题

单片机C语言If和for等基本语句结构

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-10-28 14:08 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

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

x
if和for,这两个从本质上来说,是不是C语言的两个关键字呀。那么我们为什么又把它称之为C语言的基本结构的一部分呢。要回答这个问题,我们是不是首先要搞清楚C语言的基本结构是什么?
2 l4 m2 U( A3 q, D
* [7 W- U8 @: V实际上,任何结构化编程语言的基本结构都是相同的,也就是三种基本的程序结构:顺序,分支和循环。由这三者最基本的结构,可以搭建出任何我们想实现的程序结构。在狄杰斯特拉(Edsger W. Dijkstra)反复研究面条式代码(spaghetti code),并在1968年给某位编辑写了一篇著名的简信,题为《Go to语句是有害的》之后,计算机科学家Corrado Bohm和Giuseppe Jacopini证明,使用顺序(sequencing),分支/选择(alternation)和循环(iteration)这三种流程结构就足以表达所有程序的本质。C语言作为结构化编程语言的一种,其程序结构,自然也是由这三种最基本的程序结构组成。: T7 g  y6 w0 M# M2 {* V5 H
( p( O* S9 _$ p8 a, p2 w5 p
顺序执行程序,这个很好理解,一条语句接着一条语句执行就可以了。那么C语言的分支和循环是如何实现的呢?( V3 Q/ e, h$ E/ J: C5 |0 v5 m0 T! S

. I9 j, Q% Q9 R: c对于分支,我们常见的关键词是不是有if/else和switch/case两种组合呀。if/else翻译过来,是不是就是“如果…,否则…”,是一个条件判断。如果用伪代码的方式来进行表达的话,一般有这两种形式。
; q+ A: q5 B2 l, u& u# F" \' Q) T' X& H7 E. A% t
第一种形式如下:$ [$ s9 }, k& e" d, z( M
if(条件为真)
1 s1 u4 w( a6 D& j2 |* G* @5 @{3 b" F' h6 U  m6 d' h
代码段1;
! N4 f, m. K' n. @}9 M0 n1 K. H1 {- I6 M$ U
else
* O* r; D& s% U{
. [' K* u. ^* r# K8 d1 q& p代码段2;& C" \! x, h  h8 ~& a3 I
}
/ D3 O6 X, l, L& T2 X3 ^这里else的含义其实就是条件不为真,那么也就是条件为假。
7 M; J4 I- {: i1 W' F3 ~. d

# Y  G+ l3 F+ h6 [  x第二种形式是这样的:
3 B  d; t) k+ A, Wif(条件1为真)# k0 ?' a' R6 s. f) E! ^
{3 D  j! m( h) a" O7 @: `
代码段1;8 C2 `8 N* c7 p( d, r
}4 d8 [8 q- }& l+ Y9 P; S
else if(条件2为真)
8 b+ B+ a& }% E- O{
, N2 `$ ~8 {2 E: B代码段2;; `. N: O1 l, n1 v2 {6 F0 R
}- S' V& H0 }7 L- a: b
else1 H4 A: R1 J: G5 _. h- O0 O3 R
{' z' C6 m/ p# Q+ O. g
代码段3;
5 u' X  T: n/ }9 v
  b3 Z3 P" O/ e}' p& i& I( u( O1 q; ?) Z

: Q2 q9 s, r  }  ~% M' G8 a' v第一种形式和第二种形式本质上的区别,其实就是第一个是双分支,第二个是多分支。两种不同的分支,我们要根据具体情况去使用。某种意义上多分支模式可以由双分支演变而来,比如我们可以在双分支模式里面的else里嵌套一个双分支结构就可以了。
2 O2 I0 r8 }1 A8 n' x' p
2 K( n5 s- V# t5 E
* E5 f1 }& v9 w( a  uif(条件1为真)0 U/ y% q1 p; V4 }6 K5 x( y' S
{
5 l8 y3 o- q* D. K# ]% x代码段1;, F- L1 O5 Y6 y' U
}! ^! G( Y' ?$ j4 E# ]
else  \! E# @# v6 T/ k
{, ~+ t/ N2 D: e, r5 O6 n" ^
if(条件2为真)
# O& z, B* {- E, ^. |* P7 ?{# ~3 m( e6 @% J7 p
代码段2;
# [; @! z+ `' i. w}) U; q+ m( q0 U/ I4 u0 [7 g1 d, c
else, L$ `+ Z6 o8 x( p* X+ J
{. Q0 z; ^8 O* ?5 o' M! d3 q1 L; t" e
代码段3;
2 g& W. G! G' Y% O& s0 y; p- E}
& s) z2 w# s  B/ h% e" O}! e' ~& D% s7 w: z" {% Y# |
从这个意义上看,双分支和多分支其实是一回事情,本质上都是分支。分支这个概念,大家应该都是相对容易接受的,任何一件事情总有它的对立面,高对低,胖对瘦,大对小,物质对暗物质等等。分支这个概念应该是反映了事物的一种本源的状态,是描述程序是不可再进行切分的维度,也就是说分支成为了任何程序的三种基本结构之一。
; J" `  h& b- W, B. U/ Z$ |; M1 D- W" u
其实对于多分支的情况,C语言有另外一套关键字组合switch/case,写成伪代码的形式,大概是这样的。
7 o$ K6 y: u0 a- i7 `
; a1 f2 l0 I% `- N7 Yswitch(变量){7 \$ O# \: K1 m. q9 i6 V7 u6 O' z# u
case 常数1:
( J1 J& Z3 o# _5 P" ~代码段1;, R% n* @6 W2 ~. I* d$ G, K
break;
+ x4 w) s3 c+ h3 `- n7 _% \case 常数2:
: {7 c2 N" G0 G0 W* [代码段2;
+ S5 ]7 Z; j8 L- @7 o- ^4 {break;
, X$ x1 [7 u% Y' k& O' {: ^8 M& fcase 常数3:
) u1 b( w9 j' a! O4 {6 J9 R代码段3;/ M: u0 h( b$ m" |- v9 g6 R
break;
. M( K$ t! K4 x1 D+ A。。。
$ J  \9 m! I% ~# K2 M, Hdefault:8 i7 ?' E9 @' G  _$ }$ }* K
代码段n;6 ]8 M8 @6 ~. ]3 O- o5 W
break;
" G  U6 I3 L! W4 p5 ~/ T}* r% v0 _9 L. o2 p2 O+ H

. ~+ _/ B  W7 A: b大家注意没,对于switch/case组合来说,它的条件一定要是常量,而且要是整数。这个是不是对判断的条件作出了限制呀。这里的default关键字,是和if/else里面的else对应的,表示意外情况。从表面看,switch/case适用于逻辑条件简单,但是分类较多的情况;if/else适用于判断条件复杂,但是分支较少的情况。但是从另外一个层面看来,switch/case所具备的功能,if/else完成起来,完全没有问题呀。那为什么还要搞出来这一个关键字组合呢?
% h$ V2 G( V. W3 y我个人的理解是switch/case关键字的执行效率,在某些情况下,要比if/else要高。, k; n; j& Z1 S' p5 d/ j, O8 ?' H

+ Y( N5 E) O" W( c+ Qint a = 0;
: M/ {( R4 F  ?, Y' X: O4 Cswitch(a)0 K+ t7 A4 C8 W' @1 Y0 m
{! ]$ \* ~! x9 @, J
case -1:
$ N: Y: z) _+ Y* J" f+ \; Z1 i    break;
' T, k- |2 B( W. d/ X: H3 l: d8 p" kcase -2:
' b' d+ E  l) `0 g3 c    break;0 ]; j0 e2 J: d& h6 |. E
case -3:
2 P& Q. ?" a7 ]    break;
. Z5 D& W2 M2 m* q. o/ fcase -4:
) g+ A. g& k. |+ [( D    break;5 z, J5 f, l6 U# }
case 0:
6 K- Z) c7 [$ ]9 _! S" Z    printf("I am in switch case!\n");
4 H9 f; ?  C$ N    break;
4 A9 d+ D* H- l/ W$ Q2 i( bdefault:% k: W2 S- Q. c7 i: y
  break;
' t8 W2 x2 Z$ R7 y  i}
0 H6 B& a+ J' wprintf("I am between the switch case and if/else if/else!\n");) R3 x/ B* {* |1 K
if (-1 == a)
5 f  c5 B) G, m8 L{
1 [4 Q" [8 F) t& i6 P& D}
% y# ^9 r, A$ M3 I" S/ k& helse if (-2 == a)
- j3 D2 Z8 t. i1 q: s" @{
7 o0 f" K5 H( j7 M+ V, g}: U6 u# w& Y7 Y) U) z
else if (-3 == a)
7 Y, {# ^# w" e3 _% s9 S{- B) E) z0 h. @& A
}2 l/ E$ v% g! ?7 K
else if (-4 == a)( ^' g& r; H) G1 a- G9 Y6 ~& }
{$ i5 u' d! o* M! Q' u
}
0 X9 |3 B' s* ?0 s8 ?2 N- s' \8 z& Celse if (-5 == a)
. J9 n  b0 N6 J" d7 g! B; H" O{
$ M; ?  l+ I% h7 @}
3 j( Y" q0 S. w, p8 E( t/ C3 V/ Y5 F+ e3 gelse) z8 |$ L' |: M  Y$ j, T
{4 K' T, Q% r) u* p7 T' P
     printf("I am in if/else if/else!\n");3 R0 M2 i- f0 E2 e7 b% }
}( A& o6 w; j1 L1 V. |' X2 S

9 r% f: `/ R' C比如对于上面的代码段,对于switch/case关键词对来说,程序是直接跳到case为0的情况下的;但是对于if/else而言,程序则是一句一句比较之后才达到了“else”这一句,程序执行效率的高低是显而易见的。
% W% [" q# v8 o1 U7 u& T- O9 u, H# s' e- N/ m7 ]4 B/ |
但是我们说,switch/case的程序执行效率可以比较高,并不是没有条件的。从汇编语言的层面来看,switch/case是建立了一张跳转表,因此需要一定的空间才行。这里某种程度上有以空间换时间的意思。
  I9 a/ c4 M& j$ b2 Y% y, r4 ]. G3 S  T7 W' r3 |
因此,如果程序可以使用switch/case尽量使用这个,以便提高它的执行效率。其实,我们这样比对一番之后,自己也就轻而易举地牢牢记住了它们,这个可能也就是知其然知其所以然的效果,符合人的记忆规律。1 }( l6 F4 S" D* V& {
% y4 k9 n, ~6 P, a+ @
讲完了分支,我们来看一下循环。循环这个基本结构,在C语言里面,一共有两种实现方式,for循环和while循环,其中while循环还可以分为两种,一种是while循环,一种是do/while循环。我们下面分别看一下,这三种结构的程序表达大概是什么模样。
- s1 g' }8 T5 E9 s) @
9 Y9 s/ x3 N8 t4 _( ]$ Z# }- Z/ x" wfor(循环控制变量初始化;循环终止条件;循环控制变量增量){循环体;}
# @" N% Q: Z- [) I6 U1 Ifor循环的执行步骤是:首先执行循环变量的初始化,然后执行循环终止条件;如果判断条件为假(不符合终止条件),那么就开始执行循环体;然后执行循环控制变量的增量程序,执行完以后,再去判断是不是符合循环终止条件;如何符合条件,那么就退出循环;如果不符合条件,那么就继续执行循环体,并重复执行上述步骤。
, o2 L& c( U3 Z& E1 |" o
& B* e5 z4 S  M) u; l' j感觉用第二种方式来描述这个循环体的执行过程,更为清晰。第一,先进行循环控制变量初始化;第二,执行循环终止条件,如果判断结果为假,则进入第三步;如果为假则循环终止并退出;第三,执行循环体;第四,执行循环控制变量增量,转入第二步;
7 n& i- J- L1 v8 V0 @8 W& E1 v# t- E- n
注意,其实for循环括号中的三部分其实都可以省略,如果全部省略了,就变成了一个无限循环的死循环,跳不出来了。无限循环在操作系统中使用的是非常多的,每一个任务都是一个无限循环体,包括main函数也是一个无限循环体。
4 Q: w3 c" F# I! O. w
$ @9 s4 h$ C- j- @; s1 F  W

. ?6 Z0 x: Z6 K' ?4 E! m) n
- s. ]2 A$ \3 u3 I' z

2 C& W6 T/ P9 G/ g! h8 r+ {

该用户从未签到

2#
发表于 2021-10-28 14:15 | 只看该作者
任何结构化编程语言的基本结构都是相同的

该用户从未签到

3#
发表于 2021-10-28 16:50 | 只看该作者
两种不同的分支,我们要根据具体情况去使用
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-18 00:12 , Processed in 0.140625 second(s), 26 queries , Gzip On.

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

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

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