為了提高源程序的質量和可維護性,從而最終提高軟件產品生產力,特編寫此規范。本標準規定了程序設計人員進行程序設計時必須遵循的規范。本規范主要針對單片機編程語言和08編譯器而言,包括排版、注釋、命名、變量使用、代碼可測性、程序效率、質量保證等內容。
+ Y) q+ n" L/ `9 _1.基本規則 ! |" l" r8 f5 G. n- r* i. [
格式清晰、注釋簡明扼要、命名規范易懂、函數模塊化、程序易讀易維護、功能準確實現、代碼空間效率和時間效率高、適度的可擴展性、單片機編程規范-標識符命名 - b; _7 ^ E/ d3 Z
2.標識符命名 2.1 命名基本原則
9 x3 u: F; n z, w* Z(1)命名清晰明了,有明確含義,使用完整單詞或約定俗成的縮寫。通常,較短的單詞可通過去掉元音字母形成縮寫;較長的單詞可取單詞的頭幾個字母形成縮寫。即"見名知意"。(2)命名風格要自始至終保持一致。
* m! C( ^% a1 z( E" N3 i# `" Z(3)命名中若使用特殊約定或縮寫,要有注釋說明。( X9 t6 H: O1 z
(4)同一軟件產品內模塊之間接口部分的標識符名稱之前加上模塊標識。
/ {. r$ v" P: f3 h% S5 r2.2 宏和常量命名 ' w1 d4 R* h* r; }+ b) K4 S5 F
宏和常量用全部大寫字母來命名,詞與詞之間用下劃線分隔。對程序中用到的數字均應用有意義的枚舉或宏來代替。" l G& E e3 O1 Z" R" j2 [
2.3 變量命名 * }1 `3 i/ b) Q+ @( \
變量名用小寫字母命名,每個詞的第一個字母大寫。類型前綴(u8\s8 etc.)全局變量另加前綴g_。7 s1 z$ Z7 b! v8 ?1 r2 ^
局部變量應簡明扼要。局部循環體控制變量優先使用i、j、k等;局部長度變量優先使用len、num等;臨時中間變量優先使用temp、tmp等。
; @) A& i9 t6 S6 j! F# Q8 W2.4 函數命名
, Y q% c7 S0 C8 A# [% A/ l8 K函數名用小寫字母命名,每個詞的第一個字母大寫,并將模塊標識加在最前面。
3 J2 m5 {8 b# v5 S% o2.5 文件命名
/ Y4 n8 ]' y1 l* F [, q一個文件包含一類功能或一個模塊的所有函數,文件名稱應清楚表明其功能或性質。3 c, j. A6 ~# z! ]
每個.c文件應該有一個同名的.h文件作為頭文件。 8 i( K3 l7 p$ b# o1 ~$ m
3.注釋 3.1 注釋基本原則 _/ P5 ^$ `0 N
有助于對程序的閱讀理解,說明程序在"做什么",解釋代碼的目的、功能和采用的方法。( g) y. U# B4 ^" B
一般情況源程序有效注釋量在30%左右。
" q& I F" Y) {8 B8 p; _注釋語言必須準確、易懂、簡潔。 n5 C8 m7 G7 t, q3 ]9 w+ X2 _5 o
邊寫代碼邊注釋,修改代碼同時修改相應的注釋,不再有用的注釋要刪除。
- M0 e1 o1 C; G7 M. n) S- u匯編和C中都用"//",取消";" 不使用段注釋" /* */ "(調試時可用) - t8 y" r+ O9 a( G
3.2 文件注釋 ) I6 x/ Y1 ?, `! d
文件注釋必須說明文件名、函數功能、創建人、創建日期、版本信息等相關信息。
: Z1 k) i+ h \ b& D修改文件代碼時,應在文件注釋中記錄修改日期、修改人員,并簡要說明此次修改的目的。所有修改記錄必須保持完整。$ `% B& e3 u2 P8 d& [: L
文件注釋放在文件頂端,用"/*……*/"格式包含。5 G, Q' n! G+ [" K" u: p; g7 Q
注釋文本每行縮進4個空格;每個注釋文本分項名稱應對齊。
; l5 h1 W0 f- t- y# `/***********************************************************; G2 V9 o) v: X
文件名稱:' V! U2 m: T5 x/ D$ X
作 者:
5 R' e( v2 O: c b+ ], k版 本:
' b/ L- n0 {7 [% H- ^; K說 明:$ g3 R7 B6 Y: M7 y% l3 O" g. q. R
修改記錄:* C$ y- h4 B4 c; v
***********************************************************/) ?2 T" O3 ^1 `* z, N* i
3.3 函數注釋 . t3 o( x: j* [ q+ @& D$ z) E
3.3.1 函數頭部注釋
, A1 v+ q9 W; O/ E函數頭部注釋應包括函數名稱、函數功能、入口參數、出口參數等內容。如有必要還可增加作者、創建日期、修改記錄(備注)等相關項目。
5 Y/ u! P. A% s函數頭部注釋放在每個函數的頂端,用"/*……*/"的格式包含。其中函數名稱應簡寫為Name(),不加入、出口參數等信息。
9 P: ?1 W. [) \/***********************************************************. q9 w& ^/ Y3 A
函數名稱:
# R! r. M5 U/ T6 m1 f函數功能:
. v% W( s. ~0 U$ j% Y2 V6 c入口參數:
9 z2 C0 z! ]# |出口參數:# [& }+ Y6 x) n5 G
備 注:
% m }) K" }, Z0 C9 H7 w) T% `***********************************************************/
% j' Y9 O p; @% z$ i* ?9 F5 c3.3.2 代碼注釋
" |5 B, e& A7 e/ I' k$ }7 d" @1 {代碼注釋應與被注釋的代碼緊鄰,放在其上方或右方,不可放在下面。如放于上方則需與其上面的代碼用空行隔開。一般少量注釋應該添加在被注釋語句的行尾,一個函數內的多個注釋左對齊;較多注釋則應加在上方且注釋行與被注釋的語句左對齊信盈達嵌入式企鵝要妖氣嗚嗚吧久零就要。
; \# ^& b0 d5 @$ Q, ]4 o函數代碼注釋用"//…//"的格式。7 a7 \% ^$ K- N" Z2 v, S* ?
通常,分支語句(條件分支、循環語句等)必須編寫注釋。其程序塊結束行"}"的右方應加表明該程序塊結束的標記"end of ……", 尤其在多重嵌套時。
$ Y; \: z( H6 p5 S/ a) d4 U7 i3.4 變量、常量、宏的注釋 4 A9 ?5 ~: t; \ H8 A- p
同一類型的標識符應集中定義,并在定義之前一行對其共性加以統一注釋。對單個標識符的注釋加在定義語句的行尾。2 @- ?! q0 V7 I! Z
全局變量一定要有詳細的注釋,包括其功能、取值范圍、哪些函數或過程存取它以及存取時的注意事項等。
# }3 _, L( I) D5 i2 d1 A% b注釋用"//…//"的格式。 ; S- n6 c/ } h1 u4 @1 y ~7 K# X
4.函數 4.1 函數設計原則 , O% z& i$ G4 p( i% M
函數的基本要求:
- m% I' u) \# b- f* R2 D" U1)封裝性
^+ |, q; m* b# c, u7 {1) 正確性:程序要實現設計要求的功能。, f" B1 \; b$ s& n0 D: f1 G
2) 穩定性和安全性:程序運行穩定、可靠、安全。
7 P/ J1 V) D( E$ S- |% G3) 可測試性:程序便于測試和評價。
8 ? K" x* T$ T4) 規范/可讀性:程序書寫風格、命名規則等符合規范。
* i8 Q" J$ x. y! G$ w6 `% M5) 擴展性:代碼為下一次升級擴展留有空間和接口。
- ?: Z/ p( Q4 L% m5 q: Q6) 全局效率:軟件系統的整體效率高。0 f" s( U% b2 z9 t9 n; k4 M
7) 局部效率:某個模塊/子模塊/函數的本身效率高。
/ |$ H$ v# k+ q1 k編制函數的基本原則:, a) a3 t3 E; j( p! `
1) 單個函數的規模盡量限制在200行以內(不包括注釋和空行)。一個函數只完成一個功能。
* X* x* }0 |5 Z+ g5 n$ U, [4 F2) 函數局部變量的數目一般不超過5~10個。
e, \& o" a1 }8 X' X$ |+ @( N( P3) 函數內部局部變量定義區和功能實現區(包含變量初始化)之間空一行。
! o0 |; D- G3 V! j4) 函數名應準確描述函數的功能。通常使用動賓詞組為執行某操作的函數命名。
; J$ E% o; p: H( E( P" f/ ~5) 函數的返回值要清楚明了,尤其是出錯返回值的意義要準確無誤。" X5 W2 _: l( l z4 C7 J, _) l
6) 不要把與函數返回值類型不同的變量,以編譯系統默認的轉換方式或強制的轉換方式作為返回值返回。
+ l% z! O/ a9 G5 P0 \- L$ a7) 減少函數本身或函數間的遞歸調用。; F% ]- S4 o. V8 B
8) 盡量不要將函數的參數作為工作變量。
! P8 }! r+ f% L1 w2 G1 f* s4.2 函數定義 ' e' ]" Z* @6 V
1) 函數若沒有入口參數或者出口參數,應用void明確申明。
1 Z, K1 ]" q, J2) 函數名稱與出口參數類型定義間應該空一格且只空一格。
: Y4 `- B+ A% u6 L& T0 T6 x3) 函數名稱與括號()之間無空格。3 L0 p" H; j# c% {0 S
4) 函數形參必須給出明確的類型定義。
; W0 b- q7 N& Z4 C1 o5) 多個形參的函數,后一個形參與前一個形參的逗號分割符之間添加一個空格。9 W4 {+ |* }- q: U. K4 Q7 j* ^
6) 函數體的前后花括號"{}" 各獨占一行。0 x2 D8 T L3 n j+ X8 k- X
4.3 局部變量定義
: c. j. @- r3 W, Y1) 同一行內不要定義過多變量。
' L! b8 L5 |/ ?2) 同一類的變量在同一行內定義,或者在相鄰行定義。+ d G# A; Z# \. C+ }3 K
3) 先定義data型變量,再定義idtata型變量,再定義xdata型變量.(?)
) i: m: J, z; K5 g+ V7 ~4) 數組、指針等復雜類型的定義放在定義區的最后。5 V; |7 v2 o$ q5 O1 y/ D, |
5) 變量定義區不做較復雜的變量賦值。
0 r: O. Z- W" Q$ j/ ~4.4 功能實現區規范 4 |; x* D0 K9 L. m
1) 一行只寫一條語句。( s3 Q$ i' U* c: T, X3 F) o9 r
2) 注意運算符的優先級,并用括號明確表達式的操作順序,避免使用默認優先級信盈達嵌入式企鵝要妖氣嗚嗚吧久零就要。
" l% G6 m4 |, L3) 各程序段之間使用一個空行分隔,加以必要的注釋。程序段指能完一個較具體的功能的一行或多行代碼。程序段內的各行代碼之間相互依賴性較強。(1、2、3方式)
# J! V, h9 u# [2 [4) 不要使用難懂的技巧性很高的語句。6 e+ F" c4 G9 F k2 `& G
5) 源程序中關系較為緊密的代碼應盡可能相鄰。
% s4 F7 N( o' l- ^; }8 u6) 完成簡單功能、關系非常密切的一條或幾條語句可編寫為函數或定義為宏。
# L, u; E7 _+ t$ _8 m" s0 [* c5. 單片機編程規范-排版
5 O4 B$ U7 n4 [5.1 縮進
6 E! C4 Y' E' q0 }( d. y代碼的每一級均往右縮進4個空格的位置。不使用Tab鍵
- u, e8 z: Y8 Q6 m/ \% V4 o5.2 分行 6 N3 k+ l+ x Y7 s$ Y8 a- P; E0 D
每行語句(?????超過80個字符)要分成多行書寫;長表達式要在低優先級操作符處劃分新行,操作符放在新行之首,劃分出的新行要進適當的縮進,使排版整齊,語句可讀。避免把注釋插入分行中。9 e8 n8 U2 \* L' ?+ n
5.3 空行
0 l) g8 C' e8 v. Q% [1) 文件注釋區、頭文件引用區、函數間應該有且只有一行空行。
+ T2 L( N* T2 k2) 相鄰函數之間應該有且只有一行空行。
5 |2 ~, g/ s) }% ]3) 函數體內相對獨立的程序塊之間可以用一行空行或注釋來分隔。
$ D/ r1 l8 R+ H, d* |4) 函數注釋和對應的函數體之間不應該有空行。8 @* `" [' u8 ^0 a" Y# [
5) 文件末尾有且只有一行空行。, w1 F/ h0 `0 Y; {; A- w
5.4 空格 : m2 }3 w$ o; R" G2 X9 b5 A3 A
1) 函數語句尾部或者注釋之后不能有空格。
+ v- f+ j/ c9 a! p) l2) 括號內側(即左括號后面和右括號前面)不加空格,多重括號間不加空格。: O( e8 _8 _ Z- F4 I O! X
3) 函數形參之間應該有且只有一個空格(形參逗號后面加空格)。
& c% E J8 i; C4 D4) 同一行中定義的多個變量間應該有且只有一個空格(變量逗號后面加空格)。6 Y) F$ |; ~0 E) M8 b4 s- P$ R, ?
5) 表達式中,若有多個操作符連寫的情況,應使用空格對它們分隔:3 f5 K) r8 L& v/ ~! l' s5 C
6) 在兩個以上的關鍵字、變量、常量進行對等操作時,它們之間的操作符前后均加一個空格;在兩個以上的關鍵字、變量、常量進行非對等操作時,其前后均不應加空格;) Q6 x% h4 l/ k# K1 |- \
7) 逗號只在后面加空格;9 B1 [2 o) p% m+ k6 x+ `4 s+ N
8) 雙目操作符,如比較操作符, 賦值操作符"="、"+=",算術操作符"+"、"%",邏輯操作符"&&"、"&",位操作符"<<"、"^"等,前后均加一個空格;
! }! r8 I( x0 E. _0 A C9 K! F9) 單目操作符,如"!"、"~"、"++"、"-"、"&"(地址運算符)等,前后不加空格;- B7 R0 v! B2 d3 M- h+ X
10) "->"、"."前后不加空格;
; Z. R+ B! r& X2 H11) if、for、while、switch等關鍵字與后面的括號間加一個空格;
9 c6 O5 Z: Q0 E ?, o2 O1 W; m/ F" M5.5 花括號 % b8 {1 [) p. l; f* y- L- ?
1) if、else if、else、for、while語句無論其執行體是一條語句還是多條語句都必須加花括號,且左右花括號各獨占一行。, I* o4 t7 C$ u' M5 ~
2) do{}while()結構中,"do"和"{"均各占一行,"}"和"while();"共同占用一行。
( A! Q4 c9 M9 fif ( ) do
! k/ X8 B, w2 `& B{ {
1 o7 s0 ^* o' s$ j} }while( );/ c& ]) B# Z [# b+ K" {' F
else
; l8 c% ?( n: k% T5 ?( k/ o9 y{
$ X$ q& M) ?8 Y}
0 r4 G) R$ Q- a6 p4 }" u& o7 g嵌套越少越好,{}不準超過3層
7 E; e2 N9 Z$ D& |5.6 switch語句
) F3 d3 M0 u p! S0 a% g1) 每個case和其判據條件獨占一行。6 i' E9 z7 {9 B1 z9 J5 x7 p
2) 每個case程序塊需用break結束。特殊情況下需要從一個case塊順序執行到下一個case塊的時候除外,但需要花括號在交界處明確注釋如此操作的原因,以防止出錯。& k% t9 Y5 \! i) _" t( A
3) case程序塊之間空一行,且只空一行。' T1 p3 G4 s- l4 Z
4) 每個case程序塊的執行語句保持4個空格的縮進。/ \0 M) Y/ s G/ L* |/ z7 p
5) 一般情況下都應該包含default分支。, k- j( U* x' u7 B. b5 n& _
Switch ( )5 m) y6 Q( S8 ]7 f0 P! Y
{! {( {. C/ a( Q& A+ G4 _
case x:' l2 j1 w, f% O# K y6 y7 c) W& z% m+ i
break;
; w- d' @8 V; u3 z5 U) L1 Ncase x:
* z7 B0 v) U: @+ {1 \; e4 n1 ]break;
! A" s1 h0 W1 X; Q( N$ n( K: g6 wdefault:8 V* N0 [: U- N1 {1 ?
break;
! o4 Z3 N) y9 b1 v; w: a7 d+ c& ?}/ q+ t# Z9 G" Z4 B! G& k" l) ^
6.程序結構 6.1 基本要求 , U" s: x+ E% h7 F
1) 有main()函數的.c文件應將main()放在最前面,并明確用void聲明參數和返回值。8 ^% r+ f7 ~5 u. I4 m
2) 對由多個.c文件組成的模塊程序或完整監控程序,建立公共引用頭文件,將需要引用的庫頭文件、標準寄存器定義頭文件、自定義的頭文件、全局變量等均包含在內,供每個文件引用。通常,標準函數庫頭文件采用尖角號< >標志文件名,自定義頭文件采用雙撇號″″標志文件名。
* [) G% ~4 \9 F4 e! m9 T% s/ ~$ A3) 每個.c文件有一個對應的.h文件,.c文件的注釋之后首先定義一個唯一的文件標志宏,并在對應的.h文件中解析該標志。2 @, n3 N( ~8 S, ?3 M
在.c文件中:
+ \, j$ P' Q4 a( G1 B6 [9 r, b#define FILE_FLAG- S4 B w: I7 ]2 ~( l6 l! N
在.h文件中:&
8 r: A, }8 X1 ]! d5 g6.程序結構 6.1 基本要求 " Q# E$ G, E0 o8 `0 z
1) 有main()函數的.c文件應將main()放在最前面,并明確用void聲明參數和返回值。' S# z. N7 m0 ]5 \/ j
2) 對由多個.c文件組成的模塊程序或完整監控程序,建立公共引用頭文件,將需要引用的庫頭文件、標準寄存器定義頭文件、自定義的頭文件、全局變量等均包含在內,供每個文件引用。通常,標準函數庫頭文件采用尖角號< >標志文件名,自定義頭文件采用雙撇號″″標志文件名。
: u/ ]* ?4 k0 E, T3) 每個.c文件有一個對應的.h文件,.c文件的注釋之后首先定義一個唯一的文件標志宏,并在對應的.h文件中解析該標志。+ N8 T% J3 |3 t+ ? d( v9 P9 \
在.c文件中:
2 h9 U8 V1 I! t& E4 H* F- r#define FILE_FLAG
3 H2 y8 N) V4 m0 l+ `在.h文件中:
$ a& V& \- t3 ?5 }" S3 I. b2 f#ifdef FILE_FLAG5 F4 ~- B, J# Y! s K
#define XXX) @! ] N2 x, {
#else
( E1 |, H. c6 a# h#define XXX extern
% u/ B" d4 b! S#endif
9 d6 [& s- I" ?4) 對于確定只被某個.c文件調用的定義可以單獨列在一個頭文件中、單獨調用。
% g+ J, e+ h- ?2 [6 I3 p
e" _: K* U' ?' Q0 n |