大家好,我是痞子衡,是正經搞技術的痞子,今天痞子衡給大家講的是飛思卡爾軟體開發C語言編碼規范,
2020鼠年春節是個漫長的假期,痞子衡在家百無聊賴,翻出了2016年10月1日(這個時間是痞子衡正式開始用markdown+github寫技術文章并發表到博客園上的紀念日)之前寫的技術檔案,不翻不知道,一翻嚇一跳,從2007年上大學開始到2016年這十年間,我真的寫了非常多的技術類文章,但都不夠完整,沒有成系統,排版上也不優雅,底下有時間我會慢慢整理出來,不能讓以前的辛苦都被埋沒了,
痞子衡2016年之前所寫的那些技術文章除了原創外,也有一些是翻譯的,比如今天要分享的這篇就是2013年痞子衡剛入職飛思卡爾半導體MCU軟體團隊時為了學習C編碼規范所翻譯的(外企嘛,各種資料都是洋文),當時飛思卡爾剛成立MCU軟體團隊不久,那時候Kinetis SDK也還沒有正式推出,整個團隊必須要有一個統一且良好的編碼風格,這樣寫出來的SDK才符合大廠身份,廢話不多說,下面是編碼規范原文:
1.引言
制定此編碼風格指導手冊的目的是為了使按此規范撰寫出的C/C++代碼極易被閱讀和理解,
2.與其他編碼風格對比

3.基本排版格式
- 需要以4個空格為單位的縮進.
- 堅決不用Tab鍵,要用空格鍵.
- 所有檔案結尾必須空一行.
- 文本檔案必須用UTF-8編碼.
- 每一行不能超過100個字符.
4.檔案與注釋
- 恰當地進行代碼注釋.
- 關于注釋長度沒有具體限制,只要能提供幫助,就盡可能地注釋.
- 注釋應該解釋代碼為什么要這么做,而不是如何去做(代碼本身已經表明了如何去做).
- 選擇Doxygen檔案系統來完成注釋,除了在函式中的注釋之外(因為Doxygen不適用于個別代碼行的注釋),Doxygen也不適用于匯編.
5.標準資料型別
- 僅使用C99標準給出的整型(定義見stdint.h檔案),如uint32_t,int16_t等,不要typedef自己的整型型別,如u8,int_32,WORD等.
- 使用char 或wchar_t來表示字串,但二進制快取仍應使用uint8_t
- 僅使用C99標準給出的bool型(定義見stdbool.h檔案)來表示布爾變數,true和false表示其值. (ps: windows平臺下編譯時需自行定義,因為windows下不包含stdbool.h檔案)
6.識別符號的命名
以下是C/C++下變數、函式、typedef、宏命名的基本規則,命名規則可以接受細微改動,但要保證在同一模塊中的一致性:
- 全域函式名:全小寫,單詞用下劃線隔開
如:i2c_receive_data()- 普通變數名:Camel命名法
如:thisIsMyVariable- 結構體名和類名:Pascal命名法
如:BigBoxOfTools- 類成員函式名:Camel命名法
如:initialLongProcess()- 用typedef重命名:全小寫,單詞用下劃線隔開,加_t后綴
如:big_box_of_tools_t- 用宏命名:單詞全大寫(僅在宏中使用,且必須使用)
描述性強的,可讀性強的變數名非常重要:
- 大部分單詞都不應該縮寫,比如應用block而不是blk,應用count而不是cnt.
一些流行的縮寫還是允許的,如init或config- 完全可以接受較長的,描述性的變數名
- 布爾型變數可以使用”is”,”did”等前綴,這會清晰地表明其是一個布爾型
- 變數名應該可以表達其目的,但堅決反對匈牙利命名(加資料型別前綴)
正確: temporaryParameters, startBlock, nodeKey, isAlarmEnabled
錯誤:u32BlkNum, bEnabled
有時候為了表明范圍和目的,有些變數命名是可以加前綴和后綴的:
- 區域變數:無需前綴
- 全域變數:加g_前綴
- 靜態變數:加s_前綴
- 類成員變數:加m_前綴
- 常量:加k前綴
1):如kUnconstrained, kFirstPage, kMaxBufferBytes
2):k前綴使常量很容易被識別- typedef型變數:加_t后綴
備注:切記不要用匈牙利命名法,因為其會導致變數名難于閱讀,且型別前綴常常會與變數真正型別不同步,微軟曾是此命名法的擁堆疊,但其已意識到此命名法的缺陷,目前正在逐漸脫離此方法,
7.可除錯性
- 一系列的整型常量應該用列舉來表示,而不是用宏來定義
1):在除錯時,常量被顯示為真實的標識,而不是數字
2):便于常量的邏輯分組- 大部分情況下,使用行內函式來代替宏功能
1):在除錯中,行內函式可以被禁用,故可以跳過
2):行內函式引數有型別,而宏中引數不可以有型別
3):這個規則僅適用于當用宏來表示一段代碼時,不適用于在運算式中表示某部分的宏
8. C99標準
- 需要使用C99
C99被允許使能C++或C89語意行內- 在盡量靠近變數被使用的地方來宣告變數,而不是一律在函式頂部宣告
1):這可以很容易地找到變數的定義
2):可以方便編譯器進行優化- 單行注釋應使用//而不是/* …*/
1):大部分人認為//式注釋方便閱讀
2):免去注釋嵌套的煩惱- 多行注釋/* …*/可以被用作大段確定的內容注釋,就像Doxygen注釋頭一樣,以使得被注釋的內容突出,
9.行內功能
頭檔案中,行內功能啟用應用static inline來完成
10. C/C++通用性
頭檔案中的公用函式原型必須包含在下列陳述句中
#if defined(__cplusplus)
extern "C" {
#endif // __cplusplus
// 此處放函式原型
#if defined(__cplusplus)
}
#endif // __cplusplus
C中一般都用typedef來重命名結構體和列舉資料型別,不要提及原始的結構體或列舉型名
C++中,則不需用typedef來重命名,直接用原始的結構體或列舉型名;但是如果代碼被C/C++共享,則應遵從C風格
對于被用在C++中的函式(比如類成員)而言,如果函式不帶任何引數,則不需要一個專門的void引數來表明,而在C中這是需要的
11.花括號的使用
花括號的使用雖重要性不高,但經常起爭議
- 通常情況下,花括號應該單獨起一行,不需要額外的縮進
- 有時為了保持可讀性,可以不遵守上一規則
- 花括號使用的關鍵點在于不要將代碼湊在一起,從而使得代碼比較難閱讀;也不要因為具體格式的限定,從而打破視覺流程
使用規則可以接受細微改動,但要保證在同一模塊中的一致性,以及易于閱讀
結構體和類示例:
struct Monkey
{
int x;
};
typedef struct MonkeyTwo {
int y;
} monkey_two_t;
class Cube
{
public:
Cube(int theSize);
private:
int m_size;
};
列舉示例:
enum _my_enum
{
kValueOne = 1,
kValueTwo = 2
};
typedef enum _another {
kAnotherOne = 10,
kAnotherTwo = 20
} another_t;
函式示例:
void foo()
{
printf("hi\n");
}
If陳述句示例:
if (baz >= kMaximumBaz)
{
baz = kMaximumBaz;
}
else if (!ready)
{
makeItReady();
}
else
{
abort();
}
For陳述句示例:
for (i=0; i < 10; ++i)
{
printf("%d", i);
}
While陳述句示例:
while (!done)
{
doSomething();
}
Do-while陳述句示例:
do {
doSomething();
} while (!done);
Switch陳述句示例:
switch (value)
{
case 0:
x += 1;
break;
case 1:
{
int y;
calculateIt(&y);
break;
}
default:
return;
}
命名空間示例:
namespace fsl
{
// Don't indent namespace contents!
}
Try-catch陳述句示例:
try
{
}
catch (std::exception & e)
{
}
catch (...)
{
}
12. 關于MISRA-C規范
代碼風格基本遵照MISRA-C:20xx規范,但除了以下例外(這些例外是基于MISRA-C:2004規范的)

至此,飛思卡爾軟體開發C語言編碼規范痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、微信公眾號 平臺上,
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦,

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/17248.html
標籤:嵌入式
