仅仅因为一个特性是用他们选择的语言提供给程序员的,并不意味着他们应该使用它!在使用C开发嵌入式软件时尤其如此。虽然C为嵌入式开发人员提供了大量不可或缺的工具,但有8个内置于语言中的关键字应该完全避免或仅作为最后手段使用。让我们简单探讨一下这些保留关键字,并理解为什么我们应该尽量减少它们的使用。
保留关键字1——auto
auto关键字是一个存储类说明符,它告诉编译器正在定义的变量的存储持续时间(范围)。唯一可以使用该关键字的地方是在函数中声明一个变量,该变量在函数中创建,然后在函数完成时销毁。因为这在ANSI-C中默认发生在函数的局部变量上,所以使用这个关键字是没有用的!使用它只会让开发人员感到困惑,因此应该避免。
保留关键字2——break
break关键字最常用于switch块的case语句中。这是break语句的完全有效和最好的用法!不幸的是,break也可以用来提前退出循环。这可能是break的有效用法,但是如果循环变得嵌套和复杂,就会有危险。问题变成了使用break可能会产生意想不到的后果,中断和不执行本来应该运行的代码。基本上,break在这种情况下所做的是绕过循环的原始终止表达式。因此,建议仅将break与switch/case语句一起使用,并在循环中使用其他结构来获得所需的行为。
保留关键字3——continue
continue关键字与break和goto语句有很多相同的缺点,因为它中断了代码流,可能会让嵌入式开发人员感到困惑。正在修改代码的迷茫程序员,通常会不小心添加bug!continue语句通过强制执行控制直接转到循环的测试条件来绕过循环的正常执行。使用continue的唯一有用的地方是发生错误时,程序员希望语句序列重新开始。
保留关键字4——extern
众所周知,extern关键字只需要很少的介绍,因为默认情况下,C中的所有内容都是隐式extern!extern的问题是它让一切都全球化了!这是一种糟糕的编程实践,因为它允许每个函数和变量看到其他人,这不仅会导致可重入性问题,还会允许不相关的函数意外地修改数据。应该尽量减少使用extern,将变量定义为具有最小的范围,并尽可能多地采用封装等做法。
保留关键字5——goto
goto关键字是许多电气工程师转软件工程师的旧时代最爱。回到函数式编程的时代,主要的控制结构是goto关键字。该关键字允许程序执行跳转到程序中的指定标签。goto的问题是它的使用通常会产生让嵌入式开发人员难以阅读的代码!函数和其他流控制语句的使用有助于更好的软件实现。虽然通常建议永远不要使用goto,但它唯一有意义的地方是在函数范围内的错误处理程序中使用。
保留关键字6——inline
inline关键字实际上很酷。你可以将它添加到一个函数的前面(假设你使用的是C99编译器),而不是将该函数作为编译代码中的一个函数来调用,而是将该函数的内容粘贴到位!这意味着,不需要花费时间去调用一个函数,就像函数代码是在那里写的一样!这有两个主要问题。第一个是由编译器决定它是否实际内联代码!将关键字放在函数前面并不能保证编译器会听从开发人员的建议。其次,如果编译器确实内联了函数,如果函数在整个代码中被频繁使用,那么编译后的代码的大小可能会失去控制!
保留关键字7——restrict
restrict关键字是一个仅适用于指针的类型限定符。它是在C99中引入的,允许编译器对代码执行优化,前提是被指向的对象只能通过受限指针访问。不建议使用restrict,因为它可能会产生意想不到的副作用。
保留关键字8——register
register关键字是开发人员应该避免的另一个存储类说明符。这个关键字的意思是向编译器建议,应该通过使用一个CPU寄存器来使对象快速可用。这个关键字的一个问题是,一旦获得,它是否会遵从建议或者是否会与其他自动变量一起存储在堆栈中取决于编译器。今天的编译器非常聪明,知道存储对象和数据的最佳位置,因此最好让编译器来决定,而不是再次让可能正在阅读代码并做出错误假设的嵌入式开发人员感到困惑。