物联⽹开发必备C语⾔技巧
在物联⽹开发中中,C语⾔基础性错误的不断发⽣,会导致某些缺陷的产⽣并造成维护⽅⾯的困扰。为竭⼒避免这些C编程陷阱,这⾥有10个C语⾔技巧供⼯程师参考。
1:不要使⽤“GOTO”语句
⼆⼗⼏年前,当计算机编程尚处于起步阶段时,程序流程是由“GOTO”语句来控制。该类语句允许程序员对当前代码⾏断⾏,⽽直接进⼊另⼀个不同的代码段。列表1为简单的⽰例。
列表1 使⽤GOTO语句
编程语⾔终究开始引⼊了函数的概念,即允许程序对代码进⾏断⾏。如果已经完成,不再使⽤goto语句来表⽰代码的断⾏。函数调⽤后,函数将回到下⼀条指令。列表2为⽰例。这⼀做法改善了程序结构,提⾼了可读性。⾃此,这被视为编写程序的正确⽅法。只要看到或想到goto语句,就会让软件⼯程师退缩,产⽣本能的厌恶。其中⼀个主要的原因是,⼀个遍布goto语句的程序会让让⼈很难抓住重⼼,不便于对程序的理解和维护。
列表2 ⽤函数控制流程
2:使⽤FOR(;;)或While(1)
如果goto语句已经过时,那么对程序创建⽆限循环应该如何去做呢,这是⼀些硬件⼯程师可能会疑惑的问题。毕竟,之前都是通过创建⼀个goto语句然后再返回到main语句。解决这⼀问题就要利⽤C语⾔中已经存在的循环语句for和while(列表3和4)。
列表3 使⽤⼀个⽆限的For循环
列表4 使⽤⼀个⽆限的While循环
列表中的循环条件相对⽐较简单。for循环⽆⾮是以⽆条件情况使⽤条件语句。⽽另⼀⽅⾯,while循环是语句为真即予执⾏,这等同对任何条件的⾮零值。
3:使⽤合适的条件语句
除代码的可读性之外,程序的执⾏时间还主要依赖于做决定时所选择的条件结构类型。许多硬件⼯程师都熟悉简单的if语句的使⽤。然⽽,有时⼯程师可能没有意识到,如果第⼀个条件不正确,还可以使⽤else或else if语句。这可以节省处理器时间,⽽不必评估另⼀个条件语句。在列表5所⽰的前半部分代码中,如果Var值为1,则代码仍会查看Var是否为0。⽽在⽤了else语句的后半部分代码中,只评估第⼀个语句,之后就继续⾛下⾯的代码,这样就节省了时钟周期,使代码更加清晰。
列表5 ⽤If/Else替代只⽤If
If/else if/else语句可能并不永远适⽤。如果需要检查若⼲个可能的条件,switch语句可能更合适。这样,
处理器可以评估语句,然后从⼀个答案列表中选择下⼀步动作,⽽不⽤连续地评估⼀堆条件。列表6显⽰的例⼦与列表5⽰例的类型相同。
列表6 使⽤Switch语句
以上⽰例的寓意是,让条件语句的选择更开放,以选择出最适合的语句。这种做法使程序结构更简单,便于理解程序流程,缩短处理器的额外时钟周期。
4:避免使⽤汇编语⾔
最容易上手的编程语言
微处理器的⾃然语⾔为汇编语⾔指令。为低级别机器语⾔编程可能会为处理器提供更⾼效的代码。然⽽,⼈类并不是天⽣就会这种语⾔,并且经验表明,编写汇编语⾔会造成误解。误解会导致维护不当,更甚者,可能会使系统到处是bug.⼀般建议避免使⽤汇编语⾔。实际上,现在⼤多数编译器都能编译出⾮常⾼效的代码。采⽤C语⾔或C++语⾔等⾼级语⾔的开发,能获得更有序的结构,便于理解和维护,使代码的整体效果更好。列表7给出了⼀个⽰例,⽐较了使⼀个32位变量递增所使⽤的汇编代码和C语⾔代码。
列表7 ⽤汇编和C语⾔完成⼀个变量的递增
汇编
C代码
当然,现在仍有⼀些场合适于使⽤汇编语⾔,但这种场合仍⽐较少。⾸个推荐的场合是开发引导装载
程序。这种情况下,可能需要优化对启动过程中某个决策(启动应⽤或引导加载器)的速度。此时,分⽀判定⽤汇编代码就可能有意义了。另⼀种场合是开发⼀种在DSP上运⾏有严格时序要求的控制循环。为了从设备中的得到每个时钟周期,⽤汇编语⾔做控制循环的编码是有意义的。如果⽬前任务适合⽤汇编,应确保将其妥善存档便于有据可查,这样,未来的开发者(或未来的版本)会明⽩该代码的⽤途。
5:充分利⽤模块化
笔者最常见的经历是着⼿由硬件⼯程师开启的⼀个新项⽬往往是杂乱⽆章的代码组织。通常我们会发现,代码由⼀个单⼀的主模块组成,其中有2.5万多⾏代码。在这些应⽤中,⼀切都是全局性的,函数寥寥⽆⼏,goto语句贯穿整个代码结构。15年前这算正常,但如今已不再适⽤了!C语⾔编程使⼯程师能够将代码分成独⽴的功能模块,这简化了代码导航,同时还能够使⼯程师使⽤封装等⾯向对象技术。代码可以被组织成逻辑模块,这很有意义。虽然可能要先花点时间(⼏分钟),但从长远来看,这将能省掉很多漫长之夜,和很多调试之苦!
6:使⽤描述式变量名称
编写易于理解和维护的较⼤软件有许多障碍,其中之⼀就是变量的命名习惯。为了尽⼒缩短变量名,开发者通常会⾃创⼀些较短的、令⼈费解的助记符,往往只有他们⾃⼰才能明⽩的符号。现代语⾔使
⼀个变量名可以包含数百个字符。为了让事情清晰明确,“直截了当”地⽅法要好于其它⽅式。因此,变量名⼀⽬了然不仅有利于开发⼈员,也有利于未来的维护团队。列表8给出⼀个⽰例。
列表8 变量的命名
7:少⽤#pragma语句
C语⾔中有⼀种特殊的#pragma语句。这些语句通常处理⾮标准的句法和特性,应尽可能避免使⽤这种语句,因为它们是⾮标准的,不能从⼀个处理器移植到另⼀个处理器。有些编译器可能要求⽤这类语句完成某项任务,例如定义⼀个中断服务程序。在这种情况下,可能除了使⽤#pragma语句以外别⽆它法。如果可能,将所有的#pragma语句放在⼀个模块或⼏个模块⾥。这有助于确保在代码移植时,只需要更新⼏处代码,⽽⾮整个代码库;此外,这也将有助于防⽌移植代码的⾸次编译所带来的困扰。
8:错误往往并不是看上去那样简单
在调试⼀个C程序时,有⼀个让⼈当⼼的陷阱就是编译器错误。由于编译器的复杂性,当检测到⼀个
错误时,通常错误位于程序中的其它地⽅,⽽⾮编译器所指⽰的位置。这主要与编译器⽣成程序的步骤有关。错误类型通常是⼀致的,⼯程师可以发现的⼀些错误中,90%都是根源:
*当⼼漏掉#include⽂件。这可能会使程序开发⼈员看到完美的代码⾏,但由于未包含必要的头⽂件,编译器便会将其标志为⼀个错误,表⽰有些东西未定义。
*当⼼漏掉分号。编写C代码时最常见的错误是忘记在句末加分号。
*当⼼漏掉括号。漏写括号是代码编写过程中⼜⼀常犯的错误,或是粗⼼漏掉,或是由于键⼊错误⽽产⽣⼀个错误字符。
*当⼼漏掉逗号。在复杂的定义中很容易忘记逗号!
⼀般情况下,当弹出⼀个奇怪的编译错误对话框时,要查看该⾏前已被编译的内容。很有可能就是错误所在!它可能是出现在⼀⾏上⾯,或中间部分,或在完全不同的⽂件⾥。
不要放弃!只要具备⼀定的经验,解决这些疑难问题就会成为⼀种第⼆天性。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论