為了做一個好的設計,本身在軟硬件的配合上就需要克服無數(shù)的困難和障礙,任何一名 MCU 愛好者都不希望遇到一些因為語言和工具而產生的困擾,我們在 MCU 這種資源受限的平臺上進行 C語言的開發(fā)雖然被軟件界看起來不怎么高大上,但是 MCU 的開發(fā)目前 C 語言還是主流,為了更好的操控和調試我們的硬件,我們還是需要竭力的避免一些 C語言編程的陷阱,避免被一些高大上的變成語言或者架構干擾產品整體的進度和可靠性。
第1坑:不要使用“GOTO”語句
GOTO 語句最早源于匯編語言的跳轉,在很多年前,計算機的變成還處于起步階段,C語言開始也是尋著匯編的思路來設計的,因此就遺留下了這么一個 GOTO 語句,允許程序員自由的在代碼間翱翔。使用GOTO語句的例子
int main() {
int i = 0;
// 使用goto語句的簡單示例
goto start;
loop:
printf("Inside loop: %dn", i);
i++;
start:
if (i < 5)
goto loop;
printf("Loop finished.n");
return 0;
}
這種 goto 語句用起來簡單,但是整體程序如果來回跳轉,讀起來會非常的困難,非常繞,并且 GOTO 語句還存在以下問題:
- 可讀性差: 使用
goto
語句的代碼通常會變得難以理解,因為它允許在程序中跳轉到不同的標簽位置。這使得代碼流程變得不清晰,增加了理解代碼的難度。 - 難以維護: 當代碼包含大量
goto
語句時,很容易導致代碼的維護困難。修改代碼或添加新功能時,必須仔細考慮goto
語句的影響,以防止引入錯誤。 - 錯誤的使用可能導致問題: 如果不小心使用了錯誤的標簽,或者在不當?shù)奈恢檬褂?code>goto,可能導致程序的不正確行為。這種錯誤可能難以追蹤和修復。
- 不利于結構化編程: 使用
goto
語句可能違背結構化編程的原則,使得代碼難以按照清晰的結構組織。結構化編程強調使用順序結構、選擇結構和循環(huán)結構來構建清晰、可讀、可維護的代碼。 - 不利于調試: 調試時,跳轉語句會使程序的執(zhí)行路徑變得復雜,增加了調試的難度。代碼中的跳轉可能使得代碼不易于單步調試,阻礙了查找和修復錯誤的過程。
第2坑:使用完整的條件語句
在使用判斷語句的時候,我們尤其要注意判斷條件的完整性,我們許多工程師都熟悉簡單的if else 語句,然而有一些工程師卻沒有注意到,不同的寫法可能會浪費一些處理器的時間。比如:
if(value == 1U)
{
}
if(value == 0U)
{
}
if(value == 1U)
{
}
else
{
}
在第一種寫法中,處理器會去判斷兩次,然后根據(jù)判斷結果進行分支運行,但是如果我們寫成第二種寫法,處理器只需要判斷一次就可以了。尤其是這種判斷在一個大循環(huán)內部,這將浪費我們很多處理器時間。
另外為了代碼具備更清晰的可讀性,我們應該讓 if else 成對出現(xiàn),并且都是用{}把程序分割開來,這樣也避免我們在調試的時候復制粘貼出現(xiàn)一些錯誤,從而影響我們調試和解決問題的進度。
int main() {
int choice;
// 提示用戶輸入數(shù)字
printf("Enter a number (1-3): ");
scanf("%d", &choice);
// 使用 switch 語句根據(jù)用戶輸入執(zhí)行不同的操作
switch (choice) {
case 1:
printf("You chose option 1.n");
// 執(zhí)行操作1的代碼
break;
case 2:
printf("You chose option 2.n");
// 執(zhí)行操作2的代碼
break;
case 3:
printf("You chose option 3.n");
// 執(zhí)行操作3的代碼
break;
default:
printf("Invalid choice. Please enter a number between 1 and 3.n");
// 處理無效選擇的代碼
break;
}
return 0;
}
如果判斷分支比較多,一定是用 swich case 語句來代替 if else。道理是相同的,一定要完整且用{}將程序段分隔好。同時要注意,如果我們對分支的命中率有一定的前瞻性,那么我們最好把命中率比較高的分支放在前面。
對于 case 比較多的情況,有些編譯器會主動優(yōu)化,這時候就不必考慮命中率的問題了。
第3坑:使用FOR(;;)還是 While(1)?
MCU 的開發(fā)過程中,我們絕大部分情況下還是在使用前后臺系統(tǒng),當然即便我們跑了一些實時性的操作系統(tǒng),也避免不了使用一些無限循環(huán)的處理。
那么處理無限循環(huán)的語句目前有兩種寫法,我??吹揭恍┏跫壒こ處煏褂?while(1),而在一些操作系統(tǒng)源碼中看到的更多的是 for(;;)。
如果在 C99 的版本下,我們使用 for 來寫循環(huán)看起來更緊湊。
// while 循環(huán)的初始化
int i = 0;
while (i < 5) {
// ...
i++;
}
// for 循環(huán)的初始化
for (int i = 0; i < 5; i++) {
// ...
}
另外,我十幾年前在賽普拉斯的單片機上開發(fā),因為 flash 空間很小,需要極致優(yōu)化代碼來進行空間壓縮,這里我選擇了 for 循環(huán)的寫法可以讓空間多出一個字節(jié)來,不過現(xiàn)在的很多編譯器都已經更新了很多年了,至少在主流的 arm 平臺上他們的匯編代碼都是一樣的了。
-
mcu
+關注
關注
146文章
16898瀏覽量
349932 -
嵌入式
+關注
關注
5059文章
18975瀏覽量
302075 -
C語言
+關注
關注
180文章
7595瀏覽量
135871 -
編程
+關注
關注
88文章
3565瀏覽量
93536
發(fā)布評論請先 登錄
相關推薦
評論