看到別人的編寫的代碼規(guī)范非常羨慕,于是也整理總結(jié)一份屬于自己的編碼風(fēng)格,用于規(guī)范自己的代碼,增強(qiáng)可讀性,非標(biāo)準(zhǔn)規(guī)范。強(qiáng)制自己形成良好的編碼風(fēng)格,有利于開(kāi)發(fā)大規(guī)模程序而不顯得雜亂。 參考STM32固件庫(kù)編碼風(fēng)格和FreeRTOS編碼風(fēng)格。
一、工程文件組織結(jié)構(gòu)
新建工程文件應(yīng)包含以下全部或部分文件夾:
·usrSrc:用戶源文件,用來(lái)存放.c文件和其他的源文件。main.c應(yīng)放在這里。
·usrInc:用戶頭文件,用來(lái)存放.h文件。
·usrDoc:用戶說(shuō)明文檔,用來(lái)存放用戶在開(kāi)發(fā)過(guò)程中書寫的文檔,一般為.txt格式。例如Readme.txt,指令說(shuō)明等。
·Src:引用庫(kù)的源文件。
·Inc:應(yīng)用庫(kù)的頭文件。
·Lib:引用的庫(kù)文件。一個(gè)工程一定要包含一個(gè)main.c文件,只用來(lái)存放main函數(shù)。其余函數(shù)的定義應(yīng)在相應(yīng)的.c文件中,聲明在相應(yīng)的.h文件中。
源文件
·文件頭,文件的簡(jiǎn)介
/*************************************************************************
* Copyright (c) 2017, Jimbo Zhang
* All rights reserved.
*
* File name : USB_Ctrl.c
* Brief : USB API source code.
* Introduce the main function or content of this document briefly.
* Revision : 1.01
* Author : Jimbo Zhang
* Date : 2017.03.10
* Update : Introduce the difference from previous version.*************************************************************************/
·必要的注釋和說(shuō)明源文件應(yīng)該只包含它自己的頭文件,其他的頭文件在他自己的頭文件中包含。源文件中只聲明局部函數(shù),全局函數(shù)在頭文件中聲明。全局變量在相應(yīng)的源文件中定義,在頭文件中用extern聲明。類型定義在頭文件中定義。
/* Includes -----------------------------------------------------------*/
/*only include it's own header file, theothers header fileincluded byUSB_Ctrl.h*/#include "USB_Ctrl.h"
/* Declaration --------------------------------------------------------*/
/*here are thelocalfunction declare, globalfuction declare inheader file.*/
void delay( uint32_t n);
/* Global variable ----------------------------------------------------*/
·函數(shù)頭
/******************************************************* Brief : Delay n ms* Parameter : * n: the number of delay microsecond.* Return : None.*******************************************************/
void delay( uint32_t n)
{for( i=0; i<110; i++) ???????;
}
頭文件
·文件頭,文件的簡(jiǎn)介
/*************************************************************************
- Copyright (c) 2017, Jimbo Zhang
- All rights reserved.
-
- File name : USB_Ctrl.h
- Brief : The header file of USB_Ctrl.c.
- Revision : 1.01
- Author : Jimbo Zhang
- Date : 2017.03.10
- Update : Introduce the difference from previous version.*************************************************************************/
·必要的注釋和聲明
/* Includes -----------------------------------------------------------*/
/* Define -------------------------------------------------------------*/
/* Typedef ------------------------------------------------------------*/typedefunsignedintapiStatus; //api return code
/* Enume --------------------------------------------------------------*/
/* Extern -------------------------------------------------------------*/
/* Declaration --------------------------------------------------------*/
命名規(guī)則
參考FreeRTOS命名規(guī)則,MISRA C規(guī)范。- 定義變量時(shí)盡量使用uint8_t 、uint16_t 、uint32_t等。頭文件為stdint.h。
typedefsignedcharint8_t;typedefshortint16_t;typedefintint32_t;typedeflonglongint64_t;typedefunsignedcharuint8_t;typedefunsignedshortuint16_t;typedefunsignedintuint32_t;typedefunsignedlonglonguint64_t;
·uint32_t類型的變量使用前綴ul,這里’u’表示’unsigned’,’l’表示’long’
·uint16_t類型的變量使用前綴us,這里’u’表示’unsigned’,’s’表示’short’
·uint8_t類型的變量使用前綴uc,這里’u’表示’unsigned’,’c’表示’char’
·枚舉類型變量使用前綴e
·指針類型變量在類型基礎(chǔ)上附加前綴p,比如指向uint16_t的指針變量前綴為pus
·與MISRA指南一致,char類型變量?jī)H被允許保存ASCII字符,前綴為c
·與MISRA指南一致,char *類型變量?jī)H允許指向ASCII字符串,前綴為pc
·宏定義全部使用大寫,兩個(gè)單詞之間用下劃線隔開(kāi)。
·具有文件作用域的對(duì)象盡量聲名為static的。
·全局變量加前綴’g_’。整個(gè)工程都可以用的變量,不局限于文件作用域。
代碼風(fēng)格
·縮進(jìn):縮進(jìn)使用制表符,一個(gè)制表符等于4個(gè)空格。
·注釋:注釋單行不超過(guò)80列,特殊情況除外。
·布局:源代碼應(yīng)被設(shè)計(jì)成盡可能的易于查看和閱讀。
下面的代碼片中,第一部分展示文件布局,第二部分展示C代碼設(shè)計(jì)格式。
/* #defines, 在合理的位置添加括號(hào). */#define A_DEFINITION ( 1 )
/*
* 隨后是Static (文件內(nèi)部的)函數(shù)原型,
* 如果注釋有多行,參照本條注釋風(fēng)格---每一行都以’*’起始.
*/staticvoidprvAFunction( uint32_t ulParameter );
/* 文件作用域變量(本文件內(nèi)部使用),要在函數(shù)體定義之前. */staticBaseType_t xMyVariable.
/* 每一個(gè)函數(shù)的結(jié)束都有一行破折號(hào),破折號(hào)與下面的第一個(gè)函數(shù)之間留一行空白。*/
/*-----------------------------------------------------------*/
voidvAFunction( void)
{
/* 函數(shù)體在此定義,注意要用大括號(hào)括住 */
} /*-----------------------------------------------------------*/
staticUBaseType_t prvNextFunction( void)
{
/* 函數(shù)體在此定義. */
} /*-----------------------------------------------------------*/
/*
* 函數(shù)名字總是占一行,包括返回類型。 左括號(hào)之前沒(méi)有空格左括號(hào)之后有一個(gè)空格,
* 每個(gè)參數(shù)后面有一個(gè)空格,參數(shù)的命名應(yīng)該具有一定的描述性.
*/voidvAnExampleFunction( longlParameter1, unsignedshortusParameter2 )
{ /* 變量聲明沒(méi)有縮進(jìn). */
uint8_t ucByte;
/* 代碼要對(duì)齊. 大括號(hào)占獨(dú)自一行. */
for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ) ???
{
/* 這里再次縮進(jìn). */
}
}
/*
* for、while、do、if結(jié)構(gòu)具有相似的模式。這些關(guān)鍵字和左括號(hào)之間沒(méi)有空格。
* 左括號(hào)之后有一個(gè)空格,右括號(hào)前面也有一個(gè)空格,每個(gè)分號(hào)后面有一個(gè)空格。
* 每個(gè)運(yùn)算符的前后各一個(gè)空格。使用圓括號(hào)明確運(yùn)算符的優(yōu)先級(jí)。不允許有0
* 以外的數(shù)字(魔鬼數(shù))出現(xiàn),必要時(shí)將這些數(shù)字換成能表示出數(shù)字含義的常量或
* 宏定義。
*/for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ) ???
{
}
while( ucByte < fileBUFFER_LENGTH ) ???
{
}
/*
* 由于運(yùn)算符優(yōu)先級(jí)的復(fù)雜性,我們不能相信自己對(duì)運(yùn)算符優(yōu)先級(jí)時(shí)刻保持警惕
* 并能正確的使用,因此對(duì)于多個(gè)表達(dá)式運(yùn)算時(shí),使用括號(hào)明確優(yōu)先級(jí)順序
*/if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U?) ) ???
{
ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;
}
/* 條件表達(dá)式也要像其它代碼那樣對(duì)齊。 */#if( configUSE_TRACE_FACILITY == 1 )
{
/* 向TCB增加一個(gè)用于跟蹤的計(jì)數(shù)器. */
pxNewTCB->uxTCBNumber = uxTaskNumber;
} #endif
/*方括號(hào)前后各留一個(gè)空格*/
ucBuffer[ 0] = 0U;
ucBuffer[ fileBUFFER_LENGTH - 1U] = 0U;
編程思想
·將特定功能的代碼封裝成函數(shù)。
C語(yǔ)言編程規(guī)則
參考MISRA
·Rule1:不得使用三元操作符(? : )。
·Rule2:不得殘留被注釋掉的廢代碼。
·Rule3:所有標(biāo)識(shí)符不超過(guò)31字符。
·
Rule4:不同名空間中的變量名不得相同。例如:typedef struct MyStruct {... } MyStruct; (違規(guī))
·
struct Person {
char* name;
...
};
char name[32]; (違規(guī))
·Rule5: 不得使用char, int, float, double, long等基本類型,應(yīng)該用stdint.h中定義的類型顯示表示類型的大小,如uint16_t、int32_t等。
·Rule6:禁止使用八進(jìn)制數(shù)。(因?yàn)?86U這樣的常數(shù)很容易引起誤解)。
·Rule7:不得定義與外部作用域中某個(gè)標(biāo)識(shí)符同名的對(duì)象,以避免遮蓋外部作用域中的標(biāo)識(shí)符。
·Rule8:具有文件作用域的對(duì)象盡量聲名為static的。
·Rule9:自動(dòng)對(duì)象(棧對(duì)象)使用前必須賦初值。
·
Rule10:操作符&&和||的右側(cè)表達(dá)式不得具有副作用(side-effect)。也就是說(shuō),象 if (x == 20 && ++y == 19)這樣的表達(dá)式被禁止。
·
·
Rule11:不得對(duì)有符號(hào)數(shù)施加位操作,例如 1 << 4 將被禁止,必須寫 1UL << 4。
·
·Rule12:不得對(duì)有副作用的表達(dá)式施加sizeof操作符。
·Rule13: 除了循環(huán)控制語(yǔ)句,不得使用逗號(hào)表達(dá)式。
·Rule14:不得顯式判斷浮點(diǎn)數(shù)的相等性和不等性。
·Rule15:不得遺留“永遠(yuǎn)不會(huì)用到”的代碼。
·Rule16:除了switch語(yǔ)句,不得使用標(biāo)號(hào)(label)。
·Rule17:不得使用goto。
·Rule18:不得使用continue。
·Rule19:除了switch語(yǔ)句,不得使用break
·Rule20:if, else if, else, while, do..while, for語(yǔ)句塊必須使用{}括起。
·Rule21:循環(huán)計(jì)數(shù)器的值不得在循環(huán)體內(nèi)修改。
·Rule22:禁止任何直接和間接的遞歸函數(shù)調(diào)用。
·Rule23:不應(yīng)該使用#undef。
·Rule24:不得將宏作為參數(shù)傳給宏函數(shù)。
·Rule25:在一個(gè)宏定義中,#或##符號(hào)只能出現(xiàn)一次。
·Rule26:禁止指針運(yùn)算(代之以數(shù)組下標(biāo)運(yùn)算)。
·Rule27:禁止超過(guò)兩級(jí)的指針。
·Rule28:禁止使用指向函數(shù)的非常量指針。
·Rule29:禁止使用setjmp, longjmp。
·Rule30:禁止使用atoi, atof, atol。(這個(gè)我很贊成,建議使用strtol, strtod等函數(shù))
·Rule31:禁止使用abort, exit, getenv。
-
嵌入式
+關(guān)注
關(guān)注
5059文章
18974瀏覽量
302069 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7595瀏覽量
135868 -
編碼
+關(guān)注
關(guān)注
6文章
932瀏覽量
54731
原文標(biāo)題:嵌入式er日常!強(qiáng)制自己形成良好的編碼風(fēng)格
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論