0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式C語言的自我修養(yǎng):這樣編出來的代碼簡(jiǎn)直行云流水!

j4AI_wujianying ? 來源:?jiǎn)纹瑱C(jī)精講吳鑒鷹 ? 2020-05-14 14:43 ? 次閱讀

0 規(guī)范制定說明

0.1 箴言

技術(shù)人員設(shè)計(jì)程序的首要目的是用于技術(shù)人員溝通和交流,其次才是用于機(jī)器執(zhí)行。程序的生命力在于用戶使用,程序的成長(zhǎng)在于后期的維護(hù)及根據(jù)用戶需求更新和升級(jí)功能。

如果你的程序只能由你來維護(hù),當(dāng)你離開這個(gè)程序時(shí),你的程序也和你一起離開了,這將給公司和后來接手的技術(shù)人員帶來巨大的痛苦和損失。

因此,為了程序可讀、易理解、好維護(hù),你的程序需要遵守一定的規(guī)范,你的程序需要設(shè)計(jì)。

“程序必須為閱讀它的人而編寫,只是順便用于機(jī)器執(zhí)行?!?/p>

—— Harold Abelson 和 Gerald Jay Sussman

“編寫程序應(yīng)該以人為本,計(jì)算機(jī)第二。”

—— Steve McConnell

0.1 簡(jiǎn)介

為提高產(chǎn)品代碼質(zhì)量,指導(dǎo)儀表嵌入式軟件開發(fā)人員編寫出簡(jiǎn)潔、可維護(hù)、可靠、可測(cè)試、高效、可移植的代碼,編寫了本規(guī)范。

本規(guī)范將分為完整版和精簡(jiǎn)版,完整版將包括更多的樣例、規(guī)范的解釋以及參考材料(what & why),而精簡(jiǎn)版將只包含規(guī)則部分(what)以便查閱。

在本規(guī)范的最后,列出了一些業(yè)界比較優(yōu)秀的編程規(guī)范,作為延伸閱讀參考材料。

本規(guī)范主要包含以下兩個(gè)方面的內(nèi)容:

一:為形成統(tǒng)一編程規(guī)范,從編碼形式角度出發(fā),本規(guī)范對(duì)標(biāo)示符命名、格式與排版、注釋等方面進(jìn)行了詳細(xì)闡述。

二:為編寫出高質(zhì)量嵌入式軟件,從嵌入式軟件安全及可靠性出發(fā),本規(guī)范對(duì)由于C語言標(biāo)準(zhǔn)、C語言本身、C編譯器及個(gè)人理解導(dǎo)致的潛在危險(xiǎn)進(jìn)行說明及規(guī)避。

0.3 適用范圍

本規(guī)范適用于XXX股份有限公司儀表臺(tái)秤產(chǎn)品部嵌入式軟件的開發(fā),也對(duì)其他嵌入式軟件開發(fā)起一定的指導(dǎo)作用。

0.4 術(shù)語定義

0.4.1規(guī)范術(shù)語

原則:編程時(shí)必須堅(jiān)持的指導(dǎo)思想。

規(guī)則:編程時(shí)需要遵循的約定,分為強(qiáng)制和建議(強(qiáng)制是必須遵守的,建議是一般情況下需要遵守,但沒有強(qiáng)制性)。

說明:對(duì)原則/規(guī)則進(jìn)行必要的解釋。

實(shí)例:對(duì)此原則/規(guī)則從正、反兩個(gè)方面給出例子。

材料:擴(kuò)展、延伸的閱讀材料。

Unspecified:未詳細(xì)說明的行為,這些是必須成功編譯的語言結(jié)構(gòu),但關(guān)于結(jié)構(gòu)的行為,編譯器的編寫者有某些自由。例如C語言中的“運(yùn)算次序”問題。這樣的問題有 22 個(gè)。

在某種方式上完全相信編譯器的行為是不明智的。編譯器的行為甚至不會(huì)在所有可能的結(jié)構(gòu)中都是一致的。

Undefined:未定義行為,這些是本質(zhì)的編程錯(cuò)誤,但編譯器的編寫者不一定為此給出錯(cuò)誤信息。相應(yīng)的例子是無效參數(shù)傳遞給函數(shù),或函數(shù)的參數(shù)與定義時(shí)的參數(shù)不匹配。從安全性角度這是特別重要的問題,因?yàn)樗鼈兇砹四切┎灰欢鼙痪幾g器捕捉到的錯(cuò)誤。

Implementation-defined:實(shí)現(xiàn)定義的行為,這有些類似于“unspecified ”問題,其主要區(qū)別在于編譯器要提供一致的行為并記錄成文檔。換句話說,不同的編譯器之間功能可能會(huì)有不同,使得代碼不具有可移植性,但在任一編譯器內(nèi),行為應(yīng)當(dāng)是良好定義的。

比如用在一個(gè)正整數(shù)和一個(gè)負(fù)整數(shù)上的整除運(yùn)算“/ ”和求模運(yùn)算符“% ”。存在76個(gè)這樣的問題。

從安全性角度,假如編譯器完全地記錄了它的方法并堅(jiān)持它的實(shí)現(xiàn),那么它可能不是那樣至關(guān)重要。盡可能的情況下要避免這些問題。

0.4.2 C語言相關(guān)術(shù)語

聲明(declaration):指定了一個(gè)變量的標(biāo)識(shí)符,用來描述變量的類型,是類型還是對(duì)象,函數(shù)等。聲明,用于編譯器(compiler)識(shí)別變量名所引用的實(shí)體。以下這些就是聲明:

externintbar; externintg(int,int); doublef(int,double);[ 對(duì)于函數(shù)聲明,extern關(guān)鍵字是可以省略的 。]

定義(definition):是對(duì)聲明的實(shí)現(xiàn)或者實(shí)例化。連接器(linker)需要它(定義)來引用內(nèi)存實(shí)體。

與上面的聲明相應(yīng)的定義如下:

intbar; intg(intlhs,intrhs) { returnlhs*rhs; } doublef(inti,doubled){ returni+d; }

0.5 規(guī)則的形式

規(guī)則/原則<序號(hào)>(規(guī)則類型):規(guī)則內(nèi)容。

[原始參考]

<序號(hào)>:每條規(guī)則都有一個(gè)序號(hào),序號(hào)是按照章節(jié)目錄-**的形式,從數(shù)字1開始。例如,若在此章節(jié)有個(gè)規(guī)則的話,序號(hào)為0.5-1。

(規(guī)則類型):或者是‘強(qiáng)制’,或者是‘建議’。

規(guī)則內(nèi)容:此條規(guī)則的具體內(nèi)容。

[原始參考]:指示了產(chǎn)生本條款或本組條款的可應(yīng)用的主要來源。

1 標(biāo)示符命名規(guī)則

1.1 標(biāo)示符命名總則

規(guī)則1.1-1(強(qiáng)制):標(biāo)識(shí)符(內(nèi)部的和外部的)的有效字符不能多于31。

[UndefinedImplementation-defined]

說明:ISO 標(biāo)準(zhǔn)要求在內(nèi)部標(biāo)識(shí)符之間前31 個(gè)字符必須是不同的,外部標(biāo)識(shí)符之間前6 個(gè)字符必須是不同的(忽略大小寫)以保證可移植性。我們這里放寬了此要求,要求內(nèi)部、外部標(biāo)示符的有效字符不能多于31即可。

這樣主要是便于編譯器識(shí)別,代碼清晰易讀,并保證可移植性。

規(guī)則1.1-2(強(qiáng)制):具有內(nèi)部作用域的標(biāo)識(shí)符不應(yīng)使用與具有外部作用域的標(biāo)識(shí)符相同的名稱,在內(nèi)部作用域里具有內(nèi)部標(biāo)示符會(huì)隱藏外部標(biāo)識(shí)符。

說明:外部作用域和內(nèi)部作用域的定義如下。文件范圍內(nèi)的標(biāo)識(shí)符可以看做是具有最外部(outermost )的作用域;塊范圍內(nèi)的標(biāo)識(shí)符看做是具有更內(nèi)部(more inner)的作用域,連續(xù)嵌套的塊,其作用域更深入。如果內(nèi)部作用域標(biāo)示符和外部作用域標(biāo)示符同名,內(nèi)部作用域標(biāo)示符會(huì)覆蓋外部作用域標(biāo)示符,導(dǎo)致程序混亂。

實(shí)例:

INT8Utest; { INT8Utest;/*定義了兩個(gè)test*/ test=3;/*這將產(chǎn)生混淆*/ }

規(guī)則1.1-3(建議):具有靜態(tài)存儲(chǔ)期的對(duì)象或函數(shù)標(biāo)識(shí)符不能重用。

說明:不管作用域如何,具有靜態(tài)存儲(chǔ)期的標(biāo)識(shí)符都不應(yīng)在系統(tǒng)內(nèi)的所有源文件中重用。它包含帶有外部鏈接的對(duì)象或函數(shù),及帶有靜態(tài)存儲(chǔ)類標(biāo)識(shí)符的任何對(duì)象或函數(shù)。

在一個(gè)文件中存在一個(gè)具有內(nèi)部鏈接的標(biāo)識(shí)符,而在另外一個(gè)文件中存在著具有外部鏈接的相同名字的標(biāo)識(shí)符,或者存在兩個(gè)標(biāo)示符相同的外部標(biāo)示符。對(duì)用戶來說,這有可能導(dǎo)致混淆。

實(shí)例:

test1.c

/**定義了一個(gè)靜態(tài)文件域變量test1*/ staticINT8Utest1; voidtest_fun(void) { INT8Utest1;/*定義了一個(gè)同名的局部變量test1*/ }

test2.c

/**在另一個(gè)文件又定義了一個(gè)具有外部鏈接的文件域變量test1*/ INT8Utest1;

原則1.1-4(強(qiáng)制):標(biāo)識(shí)符的命名要清晰、明了,有明確含義,同時(shí)使用完整的單詞或大家基本可以理解的縮寫,避免使人產(chǎn)生誤解。

說明:標(biāo)示符的命名盡量做到見名知意,盡量讓別人快速理解你的代碼。

實(shí)例:

好的命名方法:

INT8U debug_message ;

INT16U err_num ;

不好的命名方法:

INT8U dbmesg ;

INT16U en ;

原則1.1-5(強(qiáng)制):常見通用的單詞縮寫盡量統(tǒng)一,不得使用漢語拼音、英語混用。

說明:簡(jiǎn)短的單詞可以使用略去‘元音’字母形成縮寫,較長(zhǎng)的單詞可以使用音節(jié)首字母單詞前幾個(gè)字母形成縮寫,針對(duì)大家公認(rèn)的單詞縮寫要統(tǒng)一。對(duì)于特定的項(xiàng)目要使用的專有縮寫應(yīng)該注明或者做統(tǒng)一說明。

實(shí)例:

常見單詞縮寫表(建議):

單詞 縮寫 單詞 縮寫
argument arg buffer buf
clock clk command cmd
compare cmp configuration cfg
device dev error err
hexadecimal hex increment inc
initialize init maximum max
message msg minimum min
parameter param previous prev
register reg semaphore sem
statistic stat synchronize syn
temp tmp

原則1.1-6(建議):用正確的反義詞組命名具有互斥意義的變量或相反動(dòng)作的函數(shù)等。

實(shí)例:常見反義詞表:

正義 反義 正義 反義
add remove begin end
create destroy insert delete
first last get release
increment decrement put get
add delete lock unlock
open close min max
old new start stop
next previous source target
show hide send receive
source destination copy pase
up down

原則1.1-7(建議):標(biāo)示符盡量避免使用數(shù)字編號(hào),除非邏輯上需要。

實(shí)例:

#defineDEBUG_0_MSG #defineDEBUG_1_MSG 應(yīng)改為更有意義的定義: #defineDEBUG_WARN_MSG #defineDEBUG_ERR_MSG

參考材料:《代碼大全第2版》(Steve McConnell 著 金戈/湯凌/陳碩/張菲 譯 電子工業(yè)出版社2006年3月)"第11章變量命的力量"。

1.2 文件命名及存儲(chǔ)規(guī)則

規(guī)則1.2-1(強(qiáng)制):文件名使用小寫字母。

說明:由于不同系統(tǒng)對(duì)文件名大小寫處理不同,Windows不區(qū)分文件名大小寫,而Linux區(qū)分。所以文件名命名均采用小寫字母,多個(gè)單詞之間可使用”_”分隔符。

實(shí)例:disp.h os_sem.c

規(guī)則1.2-2(建議):工程源碼使用GB2312編碼方式。

說明:程序里的注釋可能會(huì)使用中文,GB2312是簡(jiǎn)體中文編碼,大部分的編輯工具和集成IDE環(huán)境都支持GB2312編碼,為避免中文亂碼,建議使用GB2312對(duì)源碼進(jìn)行編碼。若需要轉(zhuǎn)換成其他編碼格式,可使用文本編碼轉(zhuǎn)換工具進(jìn)行轉(zhuǎn)換。

規(guī)則1.2-3(強(qiáng)制):工程源碼使用版本管理工具進(jìn)行版本管理。

說明:程序一般需要大量更新、修正、維護(hù)工作,且有時(shí)需要多人合作。使用版本管理工具可以幫助你提高工作效率。建議使用“Git”版本管理工具。

1.3 變量命名規(guī)則

原則1.3-1(強(qiáng)制):變量命名應(yīng)明確所代表的含義或者狀態(tài)。

說明:變量名稱可以使用名詞表述清楚的盡量使用名詞,使用名詞無法描述清楚時(shí),使用形容詞或者描述性的單詞+名詞的形式。變量一般為實(shí)體的屬性、狀態(tài)等信息,使用上述方案一般可以解決變量名的命名問題,如果出現(xiàn)命名很困難或者無法給出合理的命名方式時(shí),問題可能出現(xiàn)在整體設(shè)計(jì)上,請(qǐng)重新審視設(shè)計(jì)。

規(guī)則1.3-2(強(qiáng)制):全局變量添加”G_”前綴,全局靜態(tài)變量添加” S_ ”,局部靜態(tài)變量添加”s_”前綴。使用大小寫混合方式命名,大寫字母用于分割不同單詞。

說明:添加前綴的原因有兩個(gè)。首先,使全局變量變得更醒目,提醒技術(shù)開發(fā)人員使用這些變量時(shí)要小心。其次,添加前綴使全局變量和靜態(tài)變量變得和其他變量不一致,提醒技術(shù)開發(fā)人員盡量少用全局變量。

實(shí)例:

/**出錯(cuò)信息*/ INT8UG_ErrMsg; /**每秒鐘轉(zhuǎn)動(dòng)圈數(shù)*/ staticINT32US_CirclePerSec;

規(guī)則1.3-3(強(qiáng)制):局部變量使用小寫字母,若標(biāo)示符比較復(fù)雜,使用’_’分隔符。

說明:局部變量全部使用小寫字母,和全局變量有明顯區(qū)分,使讀者看到標(biāo)示符就知道是何種作用域的變量。

實(shí)例:

INT32Udownload_program_address;

規(guī)則1.3-4(強(qiáng)制):定義指針變量*緊挨變量名,全局指針變量使用大寫P前綴”P_”,局部指針變量使用小寫p前綴”p _”。

實(shí)例:

INT8U*P_MsgAddress;/*全局變量*/ INT8U*p_msg;/*局部變量*/

1.4 函數(shù)命名規(guī)則

原則1.4-1(強(qiáng)制):函數(shù)命名應(yīng)該明確針對(duì)什么對(duì)象做出了什么操作。

說明:函數(shù)的功能是獲取、修改實(shí)體的屬性、狀態(tài)等,采用“動(dòng)詞+名詞”的方式可以滿足上述需求,若出現(xiàn)使用此方式命名函數(shù)很困難或不能命名的情況,問題可能出現(xiàn)在整體設(shè)計(jì)上,請(qǐng)重新審視設(shè)計(jì)方案。

規(guī)則1.4-2(強(qiáng)制):具有外部鏈接的函數(shù)命名使用大小寫混合的方式,首字母大寫,用于分割不同單詞。

說明:函數(shù)具有外部鏈接屬性的含義是函數(shù)通過頭文件對(duì)外聲明后,對(duì)其他文件或模塊來說是可見的。如果一個(gè)函數(shù)要在其他模塊或者文件中使用,需要在頭文件中聲明該函數(shù)。另外,在頭文件聲明函數(shù),還可以促使編譯器檢查函數(shù)聲明和調(diào)用的一致性。

實(shí)例:

char*GetErrMsg(ErrMsg*msg);

規(guī)則1.4-3(強(qiáng)制):具有文件內(nèi)部鏈接屬性的函數(shù)命名使用小寫字母,使用’_’分隔符分割不同單詞,且使用static關(guān)鍵字限制函數(shù)作用域。

說明:函數(shù)具有內(nèi)部鏈接屬性的含義是函數(shù)只能在模塊或文件內(nèi)部調(diào)用,對(duì)文件或模塊外來說是不可見的。如果一個(gè)函數(shù)僅在模塊內(nèi)部或者文件內(nèi)部使用,需要限制函數(shù)使用范圍,使用static修飾符修飾函數(shù),使其只具有內(nèi)部鏈接屬性。

在源文件中聲明一遍具有內(nèi)部鏈接的函數(shù)同樣具有促使編譯器檢查函數(shù)聲明和調(diào)用的一致性。

實(shí)例:

staticcharget_key(void);

規(guī)則1.4-4(強(qiáng)制):函數(shù)參數(shù)使用小寫字母,各單詞之間使用“_”分割,盡量保持參數(shù)順序從左到右為:輸入、修改、輸出。

說明:函數(shù)參數(shù)順序?yàn)樾栎斎雲(yún)?shù)值(這個(gè)值一般不修改,若不需要修改使用const關(guān)鍵字修飾),需修改的參數(shù)(這個(gè)參數(shù)輸入后用于提供數(shù)據(jù),函數(shù)內(nèi)部可以修改此參數(shù)),輸出參數(shù)(這個(gè)參數(shù)是函數(shù)輸出值)。

1.5 常量的命名規(guī)則

規(guī)則1.5-1(強(qiáng)制):常量(#define定義的常量、枚舉、const定義的常量)的定義使用全大寫字母,單詞之間加 ’_’分割的命名方式。

實(shí)例:

#definePI_ROUNDED3.14 constdoublePI_ROUNDED=3.14; enumweekday{SUN,MON,TUE,WED,THU,FRI,SAT};

規(guī)則1.5-2(建議):常數(shù)宏定義時(shí),十六進(jìn)制數(shù)的表示方法為0xFF。

說明:前面0x中的x小寫,數(shù)據(jù)中的”A-F”大寫。

1.6 新定義的類型命名規(guī)范

規(guī)則1.6-1(強(qiáng)制):新定義類型名的命名應(yīng)該明確抽象對(duì)象的含義,新類型名使用大寫字母,單詞之間加’_’分割,新類型指針在類型名前增加前綴”P_”。

成員變量標(biāo)示符前加類型名稱前綴,首字母大寫用于區(qū)分各個(gè)單詞。

實(shí)例:

typedefstruct_STUDENT { StudentName; StudentAge; ...... }STUDENT,*P_STUDENT; /*STUDENT為新類型名稱,P_STUDENT為新類型指針名*/

2 外觀布局

2.1 排版與格式

2.1.1 頭文件排版

規(guī)則2.1.1-1(強(qiáng)制):頭文件排版內(nèi)容依次為包含的頭文件、宏定義、類型定義、聲明變量、聲明函數(shù)。且各個(gè)種類的內(nèi)容間空三行。

說明:頭文件是模塊對(duì)外的公用接口。在頭文件中定義的宏,可以被其他模塊引用。Project中不建議使用全部變量,若使用則需在頭文件里對(duì)外聲明。模塊對(duì)外的函數(shù)接口在模塊頭文件里聲明。

2.1.2 源文件排版

規(guī)則2.1.2-1(強(qiáng)制):源文件排版內(nèi)容依次為包含的頭文件、宏定義、具有外部鏈接屬性的全局變量定義、模塊內(nèi)部使用的static變量、具有內(nèi)部鏈接的函數(shù)聲明、函數(shù)實(shí)現(xiàn)代碼。且各個(gè)種類的內(nèi)容間空三行。

說明:模塊內(nèi)部定義的宏,只能在該模塊內(nèi)部使用。只在模塊內(nèi)部使用的函數(shù),需在源碼文件中聲明,用于促使編譯器檢查函數(shù)聲明和調(diào)用的一致性。

規(guī)則2.1.2-2(強(qiáng)制):程序塊采用縮進(jìn)風(fēng)格編寫,每級(jí)縮進(jìn)4個(gè)空格。

說明:當(dāng)前主流IDE都支持Tab縮進(jìn),使用Tab縮進(jìn)需要打開和設(shè)置相關(guān)選項(xiàng)。宏定義、編譯開關(guān)、條件預(yù)處理語句可以頂格。

規(guī)則2.1.2-3(強(qiáng)制):if、for、do、while、case、switch、defaul、typedef等語句獨(dú)占一行,且這些關(guān)鍵字后需空一格。

說明:執(zhí)行語句必須用縮進(jìn)風(fēng)格寫,屬于if、for、do、while、case、switch、default、typedef等的下一個(gè)縮進(jìn)級(jí)別。一般寫if、for、do、while等語句都會(huì)有成對(duì)出現(xiàn)的{}?,if、for、do、while等語句后的執(zhí)行語句建議增加成對(duì)的“{}”;如果if/else語句塊中只有一條語句,也需增加“{}”。

實(shí)例:

for(i=0;i

規(guī)則2.1.2-4(強(qiáng)制):進(jìn)行雙目運(yùn)算、賦值時(shí),操作符之前、之后要加空格;進(jìn)行非對(duì)等操作時(shí),如果是關(guān)系密切的立即操作符(如->),后不應(yīng)加空格。

說明:采用這種方式書寫代碼,主要目的是使代碼更清晰,使關(guān)鍵操作符更突出。

實(shí)例:

(1)比較操作符, 賦值操作符"="、 "+=",算術(shù)操作符"+"、"%",邏輯操作符"&&"、"&",位域操作符"<<"、"^"等雙目操作符的前后加空格。

If(a>b) a+=2; b=a^3;

(2)"!"、"~"、"++"、"--"、"&"(地址操作符)等單目操作符前后不加空格。

Search_dowm=!true; a++;

(3)"->"、"."、”[]”前后不加空格。

Weight=G_Car->weight; eye=People.eye; array[8]=8;

規(guī)則2.1.2-5(建議):一行只定義一個(gè)變量,一行只書寫一條執(zhí)行語句,多行同類操作時(shí)操作符盡量保持對(duì)齊。

說明:一行定義一個(gè)變量,一行只書寫一條執(zhí)行語句,方便注釋,多行同類操作對(duì)齊美觀、整潔。

實(shí)例:

events_rdy=OS_FALSE; events_rdy_nbr=0; events_stat=OS_STAT_RDY; pevents=pevents_pend; pevent=*pevents;

規(guī)則2.1.2-6(建議):函數(shù)內(nèi)部局部變量定義和函數(shù)語句之間應(yīng)空三行。

說明:局部變量定義和函數(shù)語句是相對(duì)獨(dú)立的,而且空三行可以更清晰地表示出這種獨(dú)立性。

3 注釋

3.1 注釋原則

原則3.1-1(強(qiáng)制):注釋的內(nèi)容要清楚、明了,含義準(zhǔn)確,在代碼的功能、意圖層次上進(jìn)行注釋。

說明:注釋的目的是讓讀者快速理解代碼的意圖。注釋不是為了名詞解釋(what),而是說明用途(why)。

實(shí)例:

如下注釋純屬多余:

++i;//i增加1 if(data_ready)/*如果data_ready為真*/

如下注釋無任何參考價(jià)值:

// 時(shí)間有限,現(xiàn)在是:04,根本來不及想為什么,也沒人能幫我說清楚

原則3.1-2(強(qiáng)制):注釋應(yīng)分為兩個(gè)角度進(jìn)行,首先是應(yīng)用角度,主要是告訴使用者如何使用接口(即你提供的函數(shù)),其次是實(shí)現(xiàn)角度,主要是告訴后期升級(jí)、維護(hù)的技術(shù)人員實(shí)現(xiàn)的原理和細(xì)節(jié)。

說明:每一個(gè)產(chǎn)品都可以分為三個(gè)層次,產(chǎn)品本身是一個(gè)層次,這個(gè)層次之下的是你使用的更小的組件,這個(gè)層次之上的是你為別人提供的服務(wù)。你這個(gè)產(chǎn)品的存在的價(jià)值就在于把最底層的小部件的使用細(xì)節(jié)隱藏,同時(shí)給最上層的用戶提供方便、簡(jiǎn)潔的

使用接口,滿足需求。

從這個(gè)角度來看軟件的注釋,你應(yīng)該時(shí)刻想著你寫的注釋是給那一層次的人員看的,如果是用戶,那么你應(yīng)該注重描述如何使用,如果是后期維護(hù)者,那么你應(yīng)該注重原理和實(shí)現(xiàn)細(xì)節(jié)。

原則3.1-3(強(qiáng)制):修改代碼時(shí),應(yīng)維護(hù)代碼周邊的注釋,使其代碼和注釋一致,不再使用的注釋應(yīng)刪除。

說明:注釋的目的在于幫助讀者快速理解代碼使用方法或者實(shí)現(xiàn)細(xì)節(jié),若注釋和代碼不一致會(huì)起到相反的作用。建議在修改代碼前應(yīng)該先修改注釋。

規(guī)則3.1-4(建議):代碼段不應(yīng)被“注釋掉”(comment out )。

說明:當(dāng)源代碼段不需要被編譯時(shí),應(yīng)該使用條件編譯來完成(如帶有注釋的#if或#ifdef 結(jié)構(gòu))。為這種目的使用注釋的開始和結(jié)束標(biāo)記是危險(xiǎn)的,因?yàn)镃 不支持/**/嵌套的注釋,而且已經(jīng)存在于代碼段中的任何注釋將影響執(zhí)行的結(jié)果。

3.2 文件注釋

規(guī)則3.2-1(強(qiáng)制):文件注釋需放到文件開頭,具體格式見實(shí)例。

實(shí)例:

stm32f10x_dac.h /** ****************************************************************************** *@filestm32f10x_dac.h *@briefThisfilecontainsallthefunctionsprototypesfortheDACfirmware *library. *@authorMCDApplicationTeam *@versionV3.5.0 *@date11-March-2014 *@parModification:添加函數(shù),支持********
*History *Version:V3.0.1
*Author:***
*Modification:添加函數(shù),支持********
*Version:V3.0.0
*Author:***
*Modification:添加函數(shù),支持********
************************************************************************* *@attention ********************************************************* */

說明:注釋格式可被doxygen工具識(shí)別,其中@file、@brief、@author等是doxygen工具識(shí)別的關(guān)鍵字,注釋內(nèi)容可以為中文。

3.3 函數(shù)注釋

規(guī)則3.3-1(強(qiáng)制):函數(shù)注釋分為頭文件中函數(shù)原型聲明時(shí)的注釋和源文件中函數(shù)實(shí)現(xiàn)時(shí)的注釋。頭文件中的注釋注重函數(shù)使用方法和注意事項(xiàng),源文件中的注釋注重函數(shù)實(shí)現(xiàn)原理和方法。具體格式見實(shí)例。

說明:函數(shù)原型聲明的注釋按照doxygen工具可以識(shí)別的格式進(jìn)行注釋,用于doxygen工具生成頭文件信息以及函數(shù)間的調(diào)用關(guān)系信息。

源代碼實(shí)現(xiàn)主要是注釋函數(shù)實(shí)現(xiàn)原理及修改記錄,不需按照doxygen工具要求的注釋格式進(jìn)行注釋。

實(shí)例:

頭文件函數(shù)原型聲明注釋:

/** ******************************************************************** *@briefConfiguresthediscontinuousmodefortheselectedADCregular *groupchannel. *@paramADCx:wherexcanbe1,2or3toselecttheADCperipheral. *@paramNumber:specifiesthediscontinuousmoderegularchannel *countvalue.Thisnumbermustbebetween1and8. *@retvalNone *@par Usage: *ADC_DiscModeChannelCountConfig(ADC1,6);
*@parTag: *此函數(shù)不能在中斷里調(diào)用。 ******************************************************************** */ voidADC_DiscModeChannelCountConfig(ADC_TypeDef*ADCx,INT8U_tNumber);

源文件函數(shù)實(shí)現(xiàn)注釋:

/* ******************************************************************** *@briefConfiguresthediscontinuousmodefortheselectedADCregular *groupchannel. *@paramADCx:wherexcanbe1,2or3toselecttheADCperipheral. *@paramNumber:specifiesthediscontinuousmoderegularchannel *countvalue.Thisnumbermustbebetween1and8. *@retvalNone *@parModification:修改了********
*History * Modified by:***
*Date:2013-10-10 *Modification:修改了********
******************************************************************** */ voidADC_DiscModeChannelCountConfig(ADC_TypeDef*ADCx,INT8U_tNumber) { 賦值語句*********;/*關(guān)鍵語句的注釋*/ 語句***********;/*關(guān)鍵語句的注釋格式*/ 語句*******;/*實(shí)現(xiàn)*****************功能*/ }

3.4 常量及全局變量注釋

規(guī)則3.3-1(強(qiáng)制):常量、全局變量需要注釋,注釋格式見實(shí)例。

實(shí)例:

/**Descriptionofthemacro*/ #defineXXXX_XXX_XX0 /**Descriptionofglobalvariable*/ INT8UG_xxx=0;

說明:若全局變量在.c文件中定義,又在.h文件中聲明,則在頭文件中使用doxygen

格式注釋,在源碼文件中使用 /* Description of the globalvariable */的形式。

防止doxygen生成兩遍注釋文檔信息。

3.5 局部變量及語句注釋

規(guī)則3.3-1(強(qiáng)制):局部變量,函數(shù)實(shí)現(xiàn)關(guān)鍵語句需要注釋,注釋格式見實(shí)例。

實(shí)例:

*pq->OSQIn++=pmsg;/*Insertmessageintoqueue*/ pq->OSQEntries++;/*Updatethenbrofentriesinthequeue*/ if(pq->OSQIn==pq->OSQEnd) { pq->OSQIn=pq->OSQStart;/*WrapINptrifweareatendofqueue*/ }

說明:局部變量,關(guān)鍵語句需要注釋,從功能和意圖上進(jìn)行注釋,而不是代碼的重復(fù)。多條注釋語句盡量保持對(duì)齊,實(shí)現(xiàn)美觀,整潔。

參考材料:

1. 《代碼整潔之道》(RobertC.Martin 著 韓磊 譯 人民郵電出版社2010年1月)第四章"注釋”。

2.《Doxygen中文手冊(cè)》

4 項(xiàng)目版本號(hào)命名規(guī)范

項(xiàng)目版本號(hào)管理是項(xiàng)目管理的重要方面,我們根據(jù)項(xiàng)目不同的開發(fā)階段制定了不同的版本號(hào)命名規(guī)范。

項(xiàng)目開發(fā)過程一般分為前期開發(fā)測(cè)試階段、發(fā)布階段、維護(hù)階段這三個(gè)主要階段,我們分別制定了命名規(guī)范。

4.1 開發(fā)、測(cè)試階段版本號(hào)命名

規(guī)則4.1-1(強(qiáng)制):處于開發(fā)、調(diào)試階段的項(xiàng)目,版本號(hào)使用“V0.yz”的形式。

說明:處于新開發(fā)、調(diào)試階段的項(xiàng)目,版本號(hào)使用“V0.yz” 的形式,比如新開發(fā)的項(xiàng)目正處在開發(fā)、調(diào)試階段,這時(shí)可以使用“ V0.10 ”這樣的版本號(hào)。

你認(rèn)為完成了新的功能模塊或整體架構(gòu)做了很大的修改,可以根據(jù)情況增加 Y 或者 Z的值。比如,你開發(fā)階段在“ V0.10 ”基礎(chǔ)上新增加了一個(gè)功能模塊你可以將版本號(hào)改為“V0.11”,做了比較大的修改,你可以將版本號(hào)定為“V0.20”。

4.2 正式發(fā)布階段版本號(hào)命名

規(guī)則4.2-1(強(qiáng)制):處于正式發(fā)布階段的項(xiàng)目,版本號(hào)使用“Vx.y”的形式。

說明:處于正式發(fā)布的項(xiàng)目版本號(hào)使用“Vx.y”的形式。比如,你發(fā)布了一個(gè)正式面向市場(chǎng)的項(xiàng)目,你可以使用“V1.0”作為正式的版本號(hào)。在“V1.0”基礎(chǔ)上增加功能的正式版本,你可以使用“V1.1”作為下一次正式版本的版本號(hào),在“V1.0”基礎(chǔ)上修正了大的BUG或者做了很大的改動(dòng),你可以使用“V2.0”作為下一次正式版本號(hào)。

4.3 維護(hù)階段版本號(hào)命名

規(guī)則4.3-1(強(qiáng)制):處于維護(hù)階段的項(xiàng)目,版本號(hào)使用“Vx.yz”的形式。

說明:處于維護(hù)階段的項(xiàng)目版本號(hào)使用“Vx.yz”的形式。比如在"V1.1"的基礎(chǔ)上修改了一個(gè)功能實(shí)現(xiàn)算法以實(shí)現(xiàn)高效率,則可以使用"V1.11" 來表示這是在正式發(fā)布版本“V1.1”的基礎(chǔ)上進(jìn)行的一次修正,再次修正可以使用“V1.12”。

5 嵌入式軟件安全性相關(guān)規(guī)范

5.1頭文件

原則5.1-1(強(qiáng)制):頭文件用于聲明模塊對(duì)外接口,包括具有外部鏈接的函數(shù)原型聲明、全局變量聲明、定義的類型聲明等。

說明:頭文件是模塊(Module)或單元(Unit)的對(duì)外接口。頭文件中應(yīng)放置對(duì)外部的聲明,如對(duì)外提供的函數(shù)聲明、宏定義、類型定義等。內(nèi)部使用的函數(shù)聲明不應(yīng)放在頭文件中。內(nèi)部使用的宏、枚舉、結(jié)構(gòu)定義不應(yīng)放入頭文件中。變量定義不應(yīng)放在頭文件中,應(yīng)放在.c文件中。

變量的聲明盡量不要放在頭文件中,亦即盡量不要使用全局變量作為接口。變量是模塊或單元的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),不應(yīng)通過在頭文件中聲明的方式直接暴露給外部,應(yīng)通過函數(shù)接口的方式進(jìn)行對(duì)外暴露。即使必須使用全局變量,也只應(yīng)當(dāng)在.c中定義全局變量,在.h中僅聲明變量為全局的。

參考材料:《C語言接口與實(shí)現(xiàn)》(David R. Hanson著 傅蓉 周鵬 張昆琪權(quán)威 譯 機(jī)械工業(yè)出版社 2004年1月)(英文版:"C Interfaces and Implementations")

規(guī)則5.1-2(強(qiáng)制):只能通過包含頭文件的方式使用其他.c提供的接口,禁止在.c中通過extern的方式使用外部函數(shù)接口、變量。

說明:若a.c使用了b.c定義的foo()函數(shù) ,則應(yīng)當(dāng)在b.h中聲明externintfoo(int input);并在a.c中通過#include來使用foo。禁止通過在a.c中寫externintfoo(int input)來使用foo,后面這種寫法容易在foo改變時(shí)可能導(dǎo)致聲明和定義不一致。

規(guī)則5.1-3(強(qiáng)制):使用#define定義保護(hù)符,防止頭文件重復(fù)包含。

說明:多次包含一個(gè)頭文件可以通過認(rèn)真的設(shè)計(jì)來避免。如果不能做到這一點(diǎn),就需要采取阻止頭文件內(nèi)容被包含多于一次的機(jī)制。通常的手段是為每個(gè)文件配置一個(gè)宏,當(dāng)頭文件第一次被包含時(shí)就定義這個(gè)宏,并在頭文件被再次包含時(shí)使用它以排除文件內(nèi)容。所有頭文件都應(yīng)當(dāng)使用#define 防止頭文件被多重包含,命名格式FILENAME_H_,其中FILENAME 為頭文件的名稱。

實(shí)例:

若文件名為:stm32f10x_adc.h。

#ifndefSTM32F10x_DAC_H_ #defineSTM32F10x_DAC_H_ ………… 受保護(hù)的代碼 #endif

5.2 預(yù)處理命令

規(guī)則5.2-1(強(qiáng)制):C的宏只能擴(kuò)展為用大括號(hào)括起來的初始化、常量、小括號(hào)括起來的表達(dá)式、類型限定符、存儲(chǔ)類標(biāo)識(shí)符或do-while-zero 結(jié)構(gòu)。

說明:這些是宏當(dāng)中所有可允許使用的形式。存儲(chǔ)類標(biāo)識(shí)符和類型限定符包括諸如extern、static和const這樣的關(guān)鍵字。使用任何其他形式的#define 都可能導(dǎo)致非預(yù)期的行為,或者是非常難懂的代碼。

特別的,宏不能用于定義語句或部分語句,除了do-while 結(jié)構(gòu)。宏也不能重定義語言的語法。

宏的替換列表中的所有括號(hào),不管哪種形式的 ()、{} 、[] 都應(yīng)該成對(duì)出現(xiàn)。do-while-zero 結(jié)構(gòu)(見下面實(shí)例)是在宏語句體中唯一可接受的具有完整語句的形式。do-while-zero 結(jié)構(gòu)用于封裝語句序列并確保其是正確的。

注意:在宏語句體的末尾必須省略分號(hào)。

實(shí)例:

以下是合理的宏定義:

#definePI3.14159F/*Constant*/ #defineXSTAL10000000/*Constant*/ #defineCLOCK(XSTAL/16)/*Constantexpression*/ #definePLUS2(X)((X)+2)/*Macroexpandingtoexpression*/ #defineSTORextern/*storageclassspecifier*/ #defineINIT(value){(value),0,0}/*bracedinitialiser*/ #defineREAD_TIME_32() do{ DISABLE_INTERRUPTS(); time_now=(INT32U)TIMER_HI<

以下是不合理的宏定義:

#defineunsignedintlong/*usetypedefinstead*/ #defineSTARTIFif(/*unbalanced()andlanguageredefinition*/

規(guī)則5.2-2(強(qiáng)制):在定義函數(shù)宏時(shí),每個(gè)參數(shù)實(shí)例都應(yīng)該以小括號(hào)括起來。

實(shí)例:

一個(gè)abs 函數(shù)可以定義成:

#defineabs(x)(((x)>=0)?(x):-(x))

不能定義成:

#defineabs(x)(((x)>=0)?x:-x)

如果不堅(jiān)持本規(guī)則,那么當(dāng)預(yù)處理器替代宏進(jìn)入代碼時(shí),操作符優(yōu)先順序?qū)⒉粫?huì)給出要求的結(jié)果。

考慮前面第二個(gè)不正確的定義被替代時(shí)會(huì)發(fā)生什么:

z=abs(a–b);

將給出如下結(jié)果:

z=((a–b>=0)?a–b:-a–b);

子表達(dá)式 – a - b 相當(dāng)于 (-a)-b ,而不是希望的 –(a-b) 。

把所有參數(shù)都括進(jìn)小括號(hào)中就可以避免這樣的問題。

規(guī)則5.2-3(建議):使用宏時(shí),不允許參數(shù)數(shù)值發(fā)生變化。

實(shí)例:

如下用法可能導(dǎo)致錯(cuò)誤。

#defineSQUARE(a)((a)*(a)) inta=5; intb; b = SQUARE(a++);/*結(jié)果:a = 7,即執(zhí)行了兩次增。

正確的用法是:

b=SQUARE(a); a++;/*結(jié)果:a = 6,即只執(zhí)行了一次增*/

同樣建議在調(diào)用函數(shù)時(shí),參數(shù)也不要變化,如果某次軟件升級(jí)將其中一個(gè)接口由函數(shù)實(shí)現(xiàn)轉(zhuǎn)換成宏,那參數(shù)數(shù)值發(fā)生變化的調(diào)用將產(chǎn)生非預(yù)期效果。

規(guī)則5.2-4(建議):除非必要,應(yīng)盡可能使用函數(shù)代替宏。

說明:宏能提供比函數(shù)優(yōu)越的速度,但是沒有參數(shù)檢查機(jī)制,不當(dāng)?shù)氖褂每赡墚a(chǎn)生非預(yù)期后果。

5.3 類型及類型轉(zhuǎn)換

規(guī)則5.3-1(強(qiáng)制):應(yīng)該使用標(biāo)明了大小和符號(hào)的typedef代替基本數(shù)據(jù)類型。不應(yīng)使用基本數(shù)值類型char、int、short、long、float和double,而應(yīng)使用typedef進(jìn)行類型的定義。

說明:為了程序的跨平臺(tái)移植性,我們使用typedef定義指明了大小和符號(hào)的數(shù)據(jù)類型。

實(shí)例:

此實(shí)例是根據(jù)keil for ARM的數(shù)據(jù)類型大小進(jìn)行的定義。

No. 基本數(shù)據(jù)類型 Typedef定義
1 typedef unsigned char BOOLEAN
2 typedef unsigned char INT8U
3 typedef signed char INT8S
4 typedef unsigned short INT16U
5 typedef signed short INT16S
6 typedef unsigned int INT32U
7 typedef signed int INT32S
8 typedef float FP32
9 typedef double FP64

應(yīng)根據(jù)硬件平臺(tái)和編譯器的信息對(duì)基本類型進(jìn)行定義。

規(guī)則5.3-2(建議):浮點(diǎn)應(yīng)用應(yīng)該適應(yīng)于已定義的浮點(diǎn)標(biāo)準(zhǔn)。

說明:浮點(diǎn)運(yùn)算會(huì)帶來許多問題,一些問題(而不是全部)可以通過適應(yīng)已定義的標(biāo)準(zhǔn)來克服。其中一個(gè)合適的標(biāo)準(zhǔn)是 ANSI/IEEE Std 754 [1] 。

5.3.1 顯式數(shù)據(jù)類型轉(zhuǎn)換

C 語言給程序員提供了相當(dāng)大的自由度并允許不同數(shù)值類型可以自動(dòng)轉(zhuǎn)換。由于某些功能性的原因可以引入顯式的強(qiáng)制轉(zhuǎn)換,例如:

1.用以改變類型使得后續(xù)的數(shù)值操作可以進(jìn)行

2.用以截取數(shù)值

3.出于清晰的角度,用以執(zhí)行顯式的類型轉(zhuǎn)換

為了代碼清晰的目的而插入的強(qiáng)制轉(zhuǎn)換通常是有用的,但如果過多使用就會(huì)導(dǎo)致程序的可讀性下降。正如下面所描述的,一些隱式轉(zhuǎn)換是可以安全地忽略的,而另一些則不能。

規(guī)則5.3.1-1(強(qiáng)制):強(qiáng)制轉(zhuǎn)換只能向表示范圍更窄的方向轉(zhuǎn)換,且與被轉(zhuǎn)換對(duì)象的類

型具有相同的符號(hào)。浮點(diǎn)類型值只能強(qiáng)制轉(zhuǎn)換到更窄的浮點(diǎn)類型。

說明:這條規(guī)則主要是要求需要強(qiáng)制轉(zhuǎn)換時(shí),須明確被轉(zhuǎn)換對(duì)象的表示范圍及轉(zhuǎn)換后的表示范圍。轉(zhuǎn)換時(shí)盡量保持符號(hào)一致,不同符號(hào)對(duì)象之間不應(yīng)出現(xiàn)強(qiáng)制轉(zhuǎn)換。向更寬數(shù)據(jù)范圍轉(zhuǎn)換并不能提高數(shù)據(jù)精確度,并沒有實(shí)際意義。在程序中盡量規(guī)劃好變量范圍,盡量少使用強(qiáng)制轉(zhuǎn)換。

規(guī)則5.3.1-2(強(qiáng)制):如果位運(yùn)算符 ~ 和 <

說明:當(dāng)這些操作符(~ 和<<)用在 small integer 類型(unsigned char 或unsigned short )時(shí),運(yùn)算之前要先進(jìn)行整數(shù)提升,結(jié)果可能包含并非預(yù)期的高端數(shù)據(jù)位。

例如:

INT8Uport=0x5aU; NT8Uresult_8; INT16Uresult_16; INT16Umode; result_8=(~port)>>4;/*不合規(guī)范*/

~port的值在16位機(jī)器上是 0xffa5 ,而在 32 位機(jī)器上是 0xffffffa5 。在每種情況下,result的值是0xfa ,然而期望值可能是0x0a 。

這樣的危險(xiǎn)可以通過如下所示的強(qiáng)制轉(zhuǎn)換來避免:

result_8=((INT8U)(~port))>>4;/*符合規(guī)范*/ result_16=((INT16U)(~(INT16U)port))>>4;/*符合規(guī)范*/

當(dāng)<<操作符用在 smallinteger 類型時(shí)會(huì)遇到類似的問題,高端數(shù)據(jù)位被保留下來。

例如:

result_16=((port<>6;/*不符合規(guī)范*/ result_16 的值將依賴于 int 實(shí)現(xiàn)的大小。附加的強(qiáng)制轉(zhuǎn)換可以避免任何模糊性。 result_16=((INT16U)((INT16U)port<>6;/*符合規(guī)范*/

5.3.2 隱式類型轉(zhuǎn)換

規(guī)則5.3.2-1(強(qiáng)制):以下類型之間不應(yīng)該存在隱式類型轉(zhuǎn)換。

1)有符號(hào)和無符號(hào)之間沒有隱式轉(zhuǎn)換

2)整型和浮點(diǎn)類型之間沒有隱式轉(zhuǎn)換

3)沒有從寬類型向窄類型的隱式轉(zhuǎn)換

4)函數(shù)參數(shù)沒有隱式轉(zhuǎn)換

5)函數(shù)的返回表達(dá)式?jīng)]有隱式轉(zhuǎn)換

6)復(fù)雜表達(dá)式?jīng)]有隱式轉(zhuǎn)換

5.3.3 整數(shù)后綴

規(guī)則5.3.3-1(強(qiáng)制):后綴“U”應(yīng)該用在所有unsigned 類型的常量上。

整型常量的類型是混淆的潛在來源,因?yàn)樗蕾囉谠S多因素的復(fù)雜組合,包括:

1)常數(shù)的量級(jí)

2)整數(shù)類型實(shí)現(xiàn)的大小

3)任何后綴的存在

4)數(shù)值表達(dá)的進(jìn)制(即十進(jìn)制、八進(jìn)制或十六進(jìn)制)

例如,整型常量“40000”在32位環(huán)境中是 int 類型,而在 16位環(huán)境中則是long 類型。值0x8000 在16位環(huán)境中是 unsigned int 類型,而在 32 位環(huán)境中則是(signed )int 類型。

注意:

1)任何帶有“U”后綴的值是unsigned 類型

2)一個(gè)不帶后綴的小于231的十進(jìn)制值是signed 類型

但是:

1)不帶后綴的大于或等于215的十六進(jìn)制數(shù)可能是 signed 或unsigned 類型

2)不帶后綴的大于或等于231的十進(jìn)制數(shù)可能是 signed 或unsigned 類型

常量的符號(hào)應(yīng)該明確。符號(hào)的一致性是構(gòu)建良好形式的表達(dá)式的重要原則。如果一個(gè)常數(shù)是unsigned 類型,為其加上“U”后綴將有助于避免混淆。當(dāng)用在較大數(shù)值上時(shí),后綴也許是多余的(在某種意義上它不會(huì)影響常量的類型);然而后綴的存在對(duì)代碼的清晰性是種有價(jià)值的幫助。

5.3.4 指針類型轉(zhuǎn)換

指針類型可以歸為如下幾類:

1)對(duì)象指針

2)函數(shù)指針

3)void 指針

4)空(null )指針常量(即由數(shù)值 0 強(qiáng)制轉(zhuǎn)換為 void*類型)

涉及指針類型的轉(zhuǎn)換需要明確的強(qiáng)制,除非在以下時(shí)刻:

1)轉(zhuǎn)換發(fā)生在對(duì)象指針和void 指針之間,而且目標(biāo)類型承載了源類型的所有類型標(biāo)識(shí)符。

2)當(dāng)空指針常量(void*)被賦值給任何類型的指針或與其做等值比較時(shí),空指針常量被自動(dòng)轉(zhuǎn)化為特定的指針類型。

C 當(dāng)中只定義了一些特定的指針類型轉(zhuǎn)換,而一些轉(zhuǎn)換的行為是實(shí)現(xiàn)定義的。

規(guī)則5.3.9-1(強(qiáng)制):轉(zhuǎn)換不能發(fā)生在函數(shù)指針和其他除了整型之外的任何類型指針之間。

[Undefined]

說明:

函數(shù)指針到不同類型指針的轉(zhuǎn)換會(huì)導(dǎo)致未定義的行為。這意味著一個(gè)函數(shù)指

針不能轉(zhuǎn)換成指向不同類型函數(shù)的指針。

規(guī)則5.3.9-2(強(qiáng)制):對(duì)象指針和其他除整型之外的任何類型指針之間、對(duì)象指針和其他類型對(duì)象的指針之間、對(duì)象指針和void指針之間不能進(jìn)行轉(zhuǎn)換。

[Undefined]

規(guī)則5.3.9-3(強(qiáng)制):不應(yīng)在某類型對(duì)象指針和其他不同類型對(duì)象指針之間進(jìn)行強(qiáng)制轉(zhuǎn)換。

說明:如果新的指針類型需要更嚴(yán)格的分配時(shí)這樣的轉(zhuǎn)換可能是無效的。

實(shí)例:

INT8U*p1; INT32U*p2; p2=(INT32U*)p1;/*不符規(guī)范*/

5.4 初始化、聲明與定義

規(guī)則5.4-1(強(qiáng)制):所有自動(dòng)變量在使用前都應(yīng)被賦值。

[Undefined]

說明:注意,根據(jù)ISO C[2] 標(biāo)準(zhǔn),具有靜態(tài)存儲(chǔ)期的變量缺省地被自動(dòng)賦予零值,除非經(jīng)過了顯式的初始化。實(shí)際中,一些嵌入式環(huán)境沒有實(shí)現(xiàn)這樣的缺省行為。

靜態(tài)存儲(chǔ)期是所有以static存儲(chǔ)類形式聲明的變量或具有外部鏈接的變量的共同屬性,自動(dòng)存儲(chǔ)期變量通常不是自動(dòng)初始化的。

規(guī)則5.4-2(強(qiáng)制):應(yīng)該使用大括號(hào)以指示和匹配數(shù)組和結(jié)構(gòu)的非零初始化構(gòu)造。

[Undefined]

說明:

ISO C[2]要求數(shù)組、結(jié)構(gòu)和聯(lián)合的初始化列表要以一對(duì)大括號(hào)括起來(盡管不這樣做的行為是未定義的)。本規(guī)則更進(jìn)一步地要求,使用附加的大括號(hào)來指示嵌套的結(jié)構(gòu)。它迫使程序員顯式地考慮和描述復(fù)雜數(shù)據(jù)類型元素(比如,多維數(shù)組)的初始化次序。

例如,下面的例子是二維數(shù)組初始化的有效(在ISO C [2]中)形式,但第一個(gè)與本規(guī)則相違背:

在結(jié)構(gòu)中以及在結(jié)構(gòu)、數(shù)組和其他類型的嵌套組合中,規(guī)則類似。

還要注意的是,數(shù)組或結(jié)構(gòu)的元素可以通過只初始化其首元素的方式初始化(為 0 或

NULL)。如果選擇了這樣的初始化方法,那么首元素應(yīng)該被初始化為0(或NULL),此時(shí)不需要使用嵌套的大括號(hào)。

實(shí)例:

INT16Utest[3][2]={1,2,3,4,5,6};/*不符合此規(guī)則*/ INT16Utest[3][2]={{1,2},{3,4},{5,6}};/*符合此規(guī)則*/

規(guī)則5.4-3(強(qiáng)制):在枚舉列表中,“= ”不能顯式用于除首元素之外的元素上,除非所有的元素都是顯式初始化的。

說明:

如果枚舉列表的成員沒有顯式地初始化,那么C 將為其分配一個(gè)從0 開始的整數(shù)序列,首元素為0 ,后續(xù)元素依次加 1 。

如上規(guī)則允許的,首元素的顯式初始化迫使整數(shù)的分配從這個(gè)給定的值開始。當(dāng)采用這種方法時(shí),重要的是確保所用初始化值一定要足夠小,這樣列表中的后續(xù)值就不會(huì)超出該枚舉常量所用的int 存儲(chǔ)量。

列表中所有項(xiàng)目的顯式初始化也是允許的,它防止了易產(chǎn)生錯(cuò)誤的自動(dòng)與手動(dòng)分配的混合。然而,程序員就該擔(dān)負(fù)職責(zé)以保證所有值都處在要求的范圍內(nèi)以及值不是被無意復(fù)制的。

實(shí)例:

enum colour { red = 3, blue, green, yellow = 5 }; /* 不符合此規(guī)則 */

enum colour { red = 3, blue = 4, green = 5, yellow= 5 }; /* 符合此規(guī)則 */

雖然green和yellow的值都是5,但這符合規(guī)則。

enum colour { red = 1, blue, green, yellow }; /* 符合此規(guī)則 */

規(guī)則5.4-4(強(qiáng)制):函數(shù)應(yīng)當(dāng)具有原型聲明,且原型在函數(shù)的定義和調(diào)用范圍內(nèi)都是可見的。

[Undefined]

說明:原型的使用使得編譯器能夠檢查函數(shù)定義和調(diào)用的完整性。如果沒有原型,就不會(huì)迫使編譯器檢查出函數(shù)調(diào)用當(dāng)中的一定錯(cuò)誤(比如,函數(shù)體具有不同的參數(shù)數(shù)目,調(diào)用和定義之間參數(shù)類型的不匹配)。

事實(shí)證明,函數(shù)接口是相當(dāng)多問題的肇因,因此本規(guī)則是相當(dāng)重要的。對(duì)外部函數(shù)來說,我們建議采用如下方法,在頭文件中聲明函數(shù)(亦即給出其原型),并在所有需要該函數(shù)原型的代碼文件中包含這個(gè)頭文件,在實(shí)現(xiàn)函數(shù)功能的.c文件中也包含具有原型聲明的頭文件。為具有內(nèi)部鏈接的函數(shù)給出其原型也是良好的編程實(shí)踐。

規(guī)則5.4-5(強(qiáng)制):定義或聲明對(duì)象、函數(shù)時(shí)都應(yīng)該顯示指明其類型。

規(guī)則5.4-6(強(qiáng)制):函數(shù)的每個(gè)參數(shù)類型在聲明和定義中必須是等同的,函數(shù)的返回類型也該是等同的。

[Undefined]

規(guī)則5.4-6(強(qiáng)制):函數(shù)應(yīng)該聲明為具有文件作用域。

[Undefined]

說明:在塊作用域中聲明函數(shù)會(huì)引起混淆并可能導(dǎo)致未定義的行為。

規(guī)則5.4-7(強(qiáng)制):在文件范圍內(nèi)聲明和定義的所有對(duì)象或函數(shù)應(yīng)該具有內(nèi)部鏈接,除非是在需要外部鏈接的情況下,具有內(nèi)部鏈接屬性的對(duì)象或函數(shù)應(yīng)該使用static關(guān)鍵字修飾。

說明:如果一個(gè)變量只是被同一文件中的函數(shù)所使用,那么就用static。類似地,如果一個(gè)函數(shù)只是在同一文件中的其他地方調(diào)用,那么就用 static。

使用 static存儲(chǔ)類標(biāo)識(shí)符將確保標(biāo)識(shí)符只是在聲明它的文件中是可見的,并且避免了和其他文件或庫中的相同標(biāo)識(shí)符發(fā)生混淆的可能性。具有外部鏈接屬性的對(duì)象或函數(shù)在相應(yīng)模塊的頭文件中聲明,在需要使用這些接口的模塊中包含此頭文件。

規(guī)則5.4-8(強(qiáng)制):當(dāng)一個(gè)數(shù)組聲明為具有外部鏈接,它的大小應(yīng)該顯式聲明或者通過初始化進(jìn)行隱式定義。

[Undefined]

實(shí)例:

INT8Uarray[10];/*符合規(guī)范*/ externINT8Uarray[];/*不符合規(guī)范*/ INT8Uarray[]={0,10,15};/*符合規(guī)范*/

盡管可以在數(shù)組聲明不完善時(shí)訪問其元素,然而仍然是在數(shù)組的大小可以顯式確定的情況下,這樣做才會(huì)更為安全。

5.5 控制語句和表達(dá)式

規(guī)則5.5-1(建議):不要過分依賴C 表達(dá)式中的運(yùn)算符優(yōu)先規(guī)則。

說明:括號(hào)的使用除了可以覆蓋缺省的運(yùn)算符優(yōu)先級(jí)以外,還可以用來強(qiáng)調(diào)所使用的運(yùn)算符。使用相當(dāng)復(fù)雜的C 運(yùn)算符優(yōu)先級(jí)規(guī)則很容易引起錯(cuò)誤,那么這種方法就可以幫助避免這樣的錯(cuò)誤,并且可以使得代碼更為清晰可讀。

然而,過多的括號(hào)會(huì)分散代碼使其降低了可讀性。因此,請(qǐng)合理使用括號(hào)來提高程序清晰度和可讀性。

規(guī)則5.5-1(強(qiáng)制):不能在具有副作用的表達(dá)式中使用sizeof 運(yùn)算符。

說明:當(dāng)一個(gè)表達(dá)式使用了sizeof運(yùn)算符,并期望計(jì)算表達(dá)式的值時(shí),表達(dá)式是不會(huì)被計(jì)算的。sizeof只對(duì)表達(dá)式的類型有用。

實(shí)例:

INT32S i;

INT32S j;

j = sizeof (i = 1234);

/*j的值是i類型的大小,但i的值并沒有賦值成1234 */

規(guī)則5.5-2(強(qiáng)制):邏輯運(yùn)算符 && 或 || 的右手操作數(shù)不能包含副作用。

說明:C語言中存在表達(dá)式的某些部分不會(huì)被計(jì)算到,這取決于表達(dá)式中的其他部分。邏輯操作符&&或||在進(jìn)行邏輯判斷時(shí),若僅判別左操作數(shù)就能確定true or false的情況下,邏輯操作符的右操數(shù)將被忽略。

實(shí)例:

if ( high && ( x == i++ ) ) /* 不符合規(guī)則 */

若high為false,則整個(gè)表達(dá)式的布爾值也即為false,不用再去執(zhí)行和判斷右操作數(shù)。

規(guī)則5.5-3(建議):邏輯運(yùn)算符(&&、| | 和 ! )的操作數(shù)應(yīng)該是有效的布爾數(shù)。有效布爾類型的表達(dá)式不能用做非邏輯運(yùn)算符(&&、| | 和 ! )的操作數(shù)。

說明:有效布爾類型是表示真、假的一種數(shù)據(jù)類型,產(chǎn)生布爾類型的可以是比較,邏輯運(yùn)算,但布爾類型數(shù)據(jù)只能進(jìn)行邏輯運(yùn)算。

規(guī)則5.5-4(強(qiáng)制):位運(yùn)算符不能用于基本類型(underlying type )是有符號(hào)的操作數(shù)上。

[Implementation-defined]

說明:位運(yùn)算(~ 、<<、>>、&、^ 和 | )對(duì)有符號(hào)整數(shù)通常是無意義的。比如,如果右移運(yùn)算把符號(hào)位移動(dòng)到數(shù)據(jù)位上或者左移運(yùn)算把數(shù)據(jù)位移動(dòng)到符號(hào)位上,就會(huì)產(chǎn)生問題。

規(guī)則5.5-6(建議):在一個(gè)表達(dá)式中,自增(++)和自減(- - )運(yùn)算符不應(yīng)同其他運(yùn)算符混合在一起。

說明:不建議使用同其他算術(shù)運(yùn)算符混合在一起的自增和自減運(yùn)算符是因?yàn)?/p>

1)它顯著削弱了代碼的可讀性;

2)在不同的變異環(huán)境下,會(huì)執(zhí)行不同的運(yùn)算次序,產(chǎn)生不同結(jié)果。

實(shí)例:

u8a = ++u8b +u8c--; /* 不符合規(guī)范 */

下面的序列更為清晰和安全:

++u8b; u8a=u8b+u8c; u8c--;

規(guī)則5.5-7(強(qiáng)制):浮點(diǎn)表達(dá)式不能做像‘>’ ‘<’ ‘==’ ‘!=’等 關(guān)系運(yùn)算。

說明:float、double類型的數(shù)據(jù)都有一定的精確度限制,使用不同浮點(diǎn)數(shù)表示規(guī)范或者不同硬件平臺(tái)可能導(dǎo)致關(guān)系運(yùn)算的結(jié)果不一致。

規(guī)則5.5-8(強(qiáng)制):for語句的三個(gè)表達(dá)式應(yīng)該只關(guān)注循環(huán)控制,for循環(huán)中用于計(jì)數(shù)的變量不應(yīng)在循環(huán)體中修改。

說明:for 語句的三個(gè)表達(dá)式都給出時(shí)它們應(yīng)該只用于如下目的:

第一個(gè)表達(dá)式初始化循環(huán)計(jì)數(shù)器;

第二個(gè)表達(dá)式包含對(duì)循環(huán)計(jì)數(shù)器和其他可選的循環(huán)控制變量的測(cè)試;

第三個(gè)表達(dá)式循環(huán)計(jì)數(shù)器的遞增或遞減。

規(guī)則5.5-9(強(qiáng)制):組成switch、while、do...while 或for 結(jié)構(gòu)體的語句應(yīng)該是復(fù)合語句。即使該復(fù)合語句只包含一條語句也要擴(kuò)在{}里。

實(shí)例:

for(i=0;i

規(guī)則5.5-10(強(qiáng)制):if /else應(yīng)該成對(duì)出現(xiàn)。所有的if ... else if 結(jié)構(gòu)應(yīng)該由else 子句結(jié)束。

規(guī)則5.5-11(強(qiáng)制):switch 語句中如果case 分支的內(nèi)容不為空,那么必須以break 作為結(jié)束,最后分支應(yīng)該是default分支。

5.6 函數(shù)

原則5.6-1(強(qiáng)制):編寫整潔函數(shù),同時(shí)把代碼有效組織起來。

說明:代碼簡(jiǎn)單直接、不隱藏設(shè)計(jì)者的意圖、用干凈利落的抽象和直截了當(dāng)?shù)目刂普Z句將函數(shù)有機(jī)組織起來。代碼的有效組織包括:邏輯層組織和物理層組織兩個(gè)方面。邏輯層,主要是把不同功能的函數(shù)通過某種聯(lián)系組織起來,主要關(guān)注模塊間的接口,也就是模塊的架構(gòu)。

物理層,無論使用什么樣的目錄或者名字空間等,需要把函數(shù)用一種標(biāo)準(zhǔn)的方法組織起來。例如:設(shè)計(jì)良好的目錄結(jié)構(gòu)、函數(shù)名字、文件組織等,這樣可以方便查找。

規(guī)則5.6-2(強(qiáng)制):一定要顯示聲明函數(shù)的返回值類型,及所帶的參數(shù)。如果沒有要聲明為void。

說明:C語言中不加類型說明的函數(shù),一律自動(dòng)按整型處理。

規(guī)則5.6-3(建議):不建議使用遞歸函數(shù)調(diào)用。

說明:有些算法使用分而治之的遞歸思想,但在嵌入式中??臻g有限,遞歸本身承載著可用堆??臻g過度的危險(xiǎn),這能導(dǎo)致嚴(yán)重的錯(cuò)誤。除非遞歸經(jīng)過了非常嚴(yán)格的控制,否則不可能在執(zhí)行之前確定什么是最壞情況(worst-case)的堆棧使用。

5.7 指針與數(shù)組

規(guī)則5.7-1(強(qiáng)制):除了指向同一數(shù)組的指針外,不能用指針進(jìn)行數(shù)學(xué)運(yùn)算,不能進(jìn)行關(guān)系運(yùn)算。

說明:這樣做的目的一是使代碼清晰易讀,另外避免訪問無效的內(nèi)存地址。

規(guī)則5.7-2(強(qiáng)制):指針在使用前一定要賦值,避免產(chǎn)生野指針。

規(guī)則5.7-3(強(qiáng)制):不要返回局部變量的地址。

說明:

局部變量是在棧中分配的,函數(shù)返回后占用的內(nèi)存會(huì)釋放,繼續(xù)使用這樣的內(nèi)存是危險(xiǎn)的。因此,應(yīng)該避免出現(xiàn)這樣的危險(xiǎn)。

實(shí)例:

INT8U*foobar(void) { INT8Ulocal_auto; return(&local_auto);/*不符合規(guī)范*/ }

5.8 結(jié)構(gòu)與聯(lián)合

原則5.8-1(強(qiáng)制):結(jié)構(gòu)功能單一,不要設(shè)計(jì)面面俱到的數(shù)據(jù)結(jié)構(gòu)。

說明:相關(guān)的一組信息才是構(gòu)成一個(gè)結(jié)構(gòu)體的基礎(chǔ),結(jié)構(gòu)的定義應(yīng)該可以明確的描述一個(gè)對(duì)象,而不是一組相關(guān)性不強(qiáng)的數(shù)據(jù)的集合。設(shè)計(jì)結(jié)構(gòu)時(shí)應(yīng)力爭(zhēng)使結(jié)構(gòu)代表一種現(xiàn)實(shí)事務(wù)的抽象,而不是同時(shí)代表多種。

結(jié)構(gòu)中的各元素應(yīng)代表同一事務(wù)的不同側(cè)面,而不應(yīng)把描述沒有關(guān)系或關(guān)系很弱的不同事務(wù)的元素放到同一結(jié)構(gòu)中。

5.9 標(biāo)準(zhǔn)庫

規(guī)則5.9-1(強(qiáng)制):標(biāo)準(zhǔn)庫中保留的標(biāo)識(shí)符、宏和函數(shù)不能被定義、重定義或取消定義。

[Undefined]

說明:通常 #undef 一個(gè)定義在標(biāo)準(zhǔn)庫中的宏是件壞事。同樣不好的是,#define 一個(gè)宏名字,而該名字是C 的保留標(biāo)識(shí)符或者標(biāo)準(zhǔn)庫中做為宏、對(duì)象或函數(shù)名字的C 關(guān)鍵字。

例如,存在一些特殊的保留字和函數(shù)名字,它們的作用為人所熟知,如果對(duì)它們重新定義或取消定義就會(huì)產(chǎn)生一些未定義的行為。這些名字包括defined、__LINE__、__FILE__、__DATE__ 、__TIME__、__STDC__、errno和assert。

規(guī)則5.9-2(強(qiáng)制):傳遞給庫函數(shù)的值必須檢查其有效性。

說明:

C 標(biāo)準(zhǔn)庫中的許多函數(shù)根據(jù)ISO [2] 標(biāo)準(zhǔn) 并不需要檢查傳遞給它們的參數(shù)的有效性。即使標(biāo)準(zhǔn)要求這樣,或者編譯器的編寫者聲明要這么做,也不能保證會(huì)做出充分的檢查。因此,程序員應(yīng)該為所有帶有嚴(yán)格輸入域的庫函數(shù)(標(biāo)準(zhǔn)庫、第三方庫及自己定義的庫)提供適當(dāng)?shù)妮斎胫禉z查機(jī)制。

具有嚴(yán)格輸入域并需要檢查的函數(shù)例子為:

math.h 中的許多數(shù)學(xué)函數(shù),比如:

負(fù)數(shù)不能傳遞給sqrt 或log函數(shù);

fmod 函數(shù)的第二個(gè)參數(shù)不能為零

toupper 和tolower:當(dāng)傳遞給toupper函數(shù)的參數(shù)不是小寫字符時(shí),某些實(shí)現(xiàn)能產(chǎn)生并非預(yù)期的結(jié)果(tolower 函數(shù)情況類似)

如果為ctype.h 中的字符測(cè)試函數(shù)傳遞無效的值時(shí)會(huì)給出未定義的行為

應(yīng)用于大多數(shù)負(fù)整數(shù)的abs 函數(shù)給出未定義的行為 在math.h 中,盡管大多數(shù)數(shù)學(xué)庫函數(shù)定義了它們?cè)试S的輸入域,但在域發(fā)生錯(cuò)誤時(shí)它們的返回值仍可能隨編譯器的不同而不同。因此,對(duì)這些函數(shù)來說,預(yù)先檢查其輸入值的有效性就變得至關(guān)重要。

程序員在使用函數(shù)時(shí),應(yīng)該識(shí)別應(yīng)用于這些函數(shù)之上的任何的域限制(這些限制可能

會(huì)也可能不會(huì)在文檔中說明),并且要提供適當(dāng)?shù)臋z查以確認(rèn)這些輸入值位于各自域

中。當(dāng)然,在需要時(shí),這些值還可以更進(jìn)一步加以限制。

有許多方法可以滿足本規(guī)則的要求,包括:

1.調(diào)用函數(shù)前檢查輸入值

2. 設(shè)計(jì)深入函數(shù)內(nèi)部的檢查手段。這種方法尤其適應(yīng)于實(shí)驗(yàn)室內(nèi)開發(fā)的庫,縱然它也可以用于買進(jìn)的第三方庫(如果第三方庫的供應(yīng)商聲明他們已內(nèi)置了檢查的話)。

3. 產(chǎn)生函數(shù)的“封裝”(wrapped)版本,在該版本中首先檢查輸入,然后調(diào)用原始的函數(shù)。

4. 靜態(tài)地聲明輸入?yún)?shù)永遠(yuǎn)不會(huì)采取無效的值。

注意,在檢查函數(shù)的浮點(diǎn)參數(shù)時(shí)(浮點(diǎn)參數(shù)在零點(diǎn)上為奇點(diǎn)),適當(dāng)?shù)淖龇ㄊ菆?zhí)行其是否為零的檢查。然而如果當(dāng)參數(shù)趨近于零時(shí),函數(shù)值的量級(jí)趨近無窮的話,仍然有必要檢查其在零點(diǎn)(或其他任何奇點(diǎn))上的容限,這樣可以避免溢出的發(fā)生。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5087

    文章

    19153

    瀏覽量

    306416
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7613

    瀏覽量

    137240
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1638

    瀏覽量

    49197

原文標(biāo)題:嵌入式C語言的自我修養(yǎng):這樣編出來的代碼簡(jiǎn)直行云流水!

文章出處:【微信號(hào):wujianying_danpianji,微信公眾號(hào):?jiǎn)纹瑱C(jī)精講吳鑒鷹】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何提高嵌入式代碼質(zhì)量?

    嵌入式代碼的質(zhì)量是至關(guān)重要的。本文將探討如何通過有效的開發(fā)方法和工具來提高嵌入式代碼的質(zhì)量,以確保系統(tǒng)的可靠性和可維護(hù)性。 理解嵌入式
    發(fā)表于 01-15 10:48

    新手怎么學(xué)嵌入式?

    的運(yùn)行機(jī)制。例如,了解數(shù)據(jù)結(jié)構(gòu)中的鏈表、棧和隊(duì)列,對(duì)于在嵌入式編程中管理數(shù)據(jù)非常有幫助。 2. 選擇合適的編程語言 嵌入式開發(fā)中常用的編程語言
    發(fā)表于 12-12 10:51

    嵌入式學(xué)習(xí)建議

    原理的嵌入式操作系統(tǒng)進(jìn)行學(xué)習(xí)。不要一開始就學(xué)習(xí)幾種操作系統(tǒng),理解了基本原理,實(shí)踐中確有實(shí)際需要再學(xué)習(xí)也不遲。人總是要不斷學(xué)習(xí)的。 ⑨關(guān)于匯編語言C語言的取舍。隨著:MCU對(duì)
    發(fā)表于 10-22 11:41

    一種常用嵌入式開發(fā)代碼

    使用開源協(xié)議:GPL-2.0varch簡(jiǎn)介varch(we-architecture,意為我們的框架庫)是嵌入式C語言常用代碼模塊庫,包含了嵌入式
    的頭像 發(fā)表于 09-04 08:06 ?516次閱讀
    一種常用<b class='flag-5'>嵌入式</b>開發(fā)<b class='flag-5'>代碼</b>庫

    七大嵌入式GUI盤點(diǎn)

    LCD設(shè)計(jì)提供高級(jí)支持,極大簡(jiǎn)化了LCD設(shè)計(jì)。它是使用比較廣泛的一款GUI,配合GUI Builder或App Wizard上位機(jī)軟件,用起來也比較方便。emWin以C語言代碼提供,使其成為
    發(fā)表于 09-02 10:58

    嵌入式QT常見開發(fā)方式有哪些?

    嵌入式QT常見開發(fā)方式有哪些? 嵌入式工程師在學(xué)習(xí)和使用Qt進(jìn)行開發(fā)時(shí),常見的幾種開發(fā)方式包括: 1.Qt Widgets編程: 通過C++代碼直接編寫GUI應(yīng)用程序,利用QtWi
    發(fā)表于 08-12 10:05

    嵌入式系統(tǒng)怎么學(xué)?

    一系列課程和技術(shù),包括但不限于以下內(nèi)容: 1、基礎(chǔ)知識(shí):學(xué)習(xí)計(jì)算機(jī)組成原理、數(shù)字電路、模擬電路等基礎(chǔ)知識(shí),建立對(duì)計(jì)算機(jī)硬件的認(rèn)知與理解。 2、編程語言:掌握至少一種嵌入式系統(tǒng)常用的編程語言,如
    發(fā)表于 07-02 10:10

    如何提升嵌入式編程能力?

    /C++:大多數(shù)嵌入式系統(tǒng)使用CC++編程語言,因此深入學(xué)習(xí)這兩種語言是非常重要的。 8. 理
    發(fā)表于 06-21 10:01

    ESP32C3編出來的組件靜態(tài)庫不完整是什么原因?

    最近從 ESP32切到了 ESP32C3,發(fā)現(xiàn) riscv編譯鏈編出來的組件不完整——例如 mbedtls組件,之前在 ESP32平臺(tái)、使用 xtensa編出來的libmbedtls.a有
    發(fā)表于 06-18 07:58

    C語言嵌入式開發(fā)中的關(guān)鍵編譯器角色

    嵌入式程序開發(fā)跟硬件密切相關(guān),需要使用C語言來讀寫底層寄存器、存取數(shù)據(jù)、控制硬件等,C語言和硬件之間由編譯器來聯(lián)系,一些
    發(fā)表于 04-26 14:53 ?663次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>:<b class='flag-5'>嵌入式</b>開發(fā)中的關(guān)鍵編譯器角色

    如何提升嵌入式C語言代碼可讀性

    接口是面向?qū)ο?b class='flag-5'>語言中的一個(gè)比較重要的概念,接口只對(duì)外部承諾實(shí)現(xiàn)該接口的實(shí)體可以完成什么樣的功能,但是不暴露實(shí)現(xiàn)的方式。這樣的好處是,實(shí)現(xiàn)者可以在不接觸接口使用者的代碼的情況下,對(duì)實(shí)現(xiàn)進(jìn)行調(diào)整。
    發(fā)表于 04-11 11:30 ?369次閱讀
    如何提升<b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>代碼</b>可讀性

    如何成為一名嵌入式C語言高手?

    高手需要掌握C語言基礎(chǔ)、了解嵌入式系統(tǒng)的硬件架構(gòu)和工作原理,通過實(shí)踐項(xiàng)目提升技能,并積極參與開源項(xiàng)目和技術(shù)社區(qū)。持續(xù)學(xué)習(xí)和自我提升是成為嵌入式
    發(fā)表于 04-07 16:03

    如何成為一名嵌入式C語言高手?

    高手需要掌握C語言基礎(chǔ)、了解嵌入式系統(tǒng)的硬件架構(gòu)和工作原理,通過實(shí)踐項(xiàng)目提升技能,并積極參與開源項(xiàng)目和技術(shù)社區(qū)。持續(xù)學(xué)習(xí)和自我提升是成為嵌入式
    發(fā)表于 03-25 14:12

    嵌入式學(xué)習(xí)步驟

    開發(fā)。 嵌入式學(xué)習(xí)步驟總結(jié)如下: (1).確定目標(biāo)平臺(tái):選擇適合您要開發(fā)的嵌入式系統(tǒng)的硬件平臺(tái)。這取決于您要控制的設(shè)備以及您需要執(zhí)行的任務(wù)。 (2).選擇編程語言嵌入式系統(tǒng)通常使用
    發(fā)表于 02-02 15:24

    聊一聊嵌入式C語言

    作為一名嵌入式軟件開發(fā)者,熟練掌握嵌入式C語言對(duì)我的日常工作至關(guān)重要。
    的頭像 發(fā)表于 01-22 09:28 ?566次閱讀