你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們講的是恩智浦 SDK 驅動的代碼風格。html
上週痞子衡受領導指示,給 SE 同事作了一個關於 SDK 代碼風格的分享。隨着組內新人的增多,這樣的培訓仍是頗有必要的。一是可讓新同事經過代碼風格來快速瞭解 SDK 驅動代碼結構,另外一方面也有利於新同事養成良好的編碼習慣。
痞子衡剛畢業時曾經也整理過一篇代碼風格 《飛思卡爾軟件開發C語言編碼規範》,現在雖已經是恩智浦紀元,但規範大多仍是類似的,僅有微小更新。此次痞子衡將新版規範的要點提取了出來,而且還提供了標準模板,這樣你們學習起來更加方便。
另外鑑於領導指定我做爲組內同事代碼風格人肉審查員(你們寫好的代碼須要由我人肉審查風格),這樣的工做若是真的徹底是人工去作,可想而言有多枯燥和低效,所以痞子衡計劃寫一個配套的自動化檢查工具,暫且叫 MCUXpresso SDK Coding Style Checker,歡迎你們來圍觀這個項目。git
- 項目地址:https://github.com/JayHeng/MCUX-SDK-Coding-Style
變量命名使用 CamelCase (小駱駝峯法),即第一個單詞以小寫字母開始,第二個單詞以及後面的每個單詞的首字母大寫,例如 myVariableNamegithub
- 做用域可在文件外的全局變量加 g_ 前綴,如 g_myVariableName
- 使用 static 修飾的全局變量加 s_ 前綴,如 s_myVariableName
- 局部變量不加任何前綴,如 myVariableName
- 其餘如 volatile, const 修飾或指針型變量,無需任何特殊表示
- 命名中的大部分單詞都不要縮寫,除非是至關流行的縮寫,如 init 或 config
宏命名使用下劃線命名法,單詞全大寫,例如 MY_MACRO_NAMEwindows
枚舉類型的命名混合了多種命名法,且加了一些特殊先後綴微信
- 枚舉類型名使用下劃線命名法,單詞全小寫,且如下劃線開頭
- 枚舉元素名使用小駱駝峯法,但統一加 k 前綴
- 可用 typedef 重命名枚舉類型名,使用下劃線命名法,但需加 _t 後綴
- 枚舉變量名使用小駱駝峯法
typedef enum _my_enumeration_name { kMyEnumerator0 = 0x00U, kMyEnumerator1 = 0x01U, kMyEnumeratorEnd = 0x02U, } my_enumeration_name_t; static my_enumeration_name_t s_myEnumVariableName;
結構體類型的命名混合了多種命名法,且加了一些特殊先後綴函數
- 結構體類型名使用下劃線命名法,單詞全小寫,且如下劃線開頭
- 結構體成員名使用小駱駝峯法
- 可用 typedef 重命名結構體類型名,使用下劃線命名法,但需加 _t 後綴
- 結構體變量名使用小駱駝峯法
typedef struct _my_struct_name { uint32_t myStructMember0; uint32_t myStructMember1; } my_struct_name_t; static my_struct_name_t s_myStructVariableName;
函數命名使用 Pascal (大駱駝峯法),即把變量名稱的第一個字母也大寫,例如 MyFunctionName工具
- 函數命名可由 [Action][Module][Feature] 組成,動做在前,特性在後。如 InitDeviceClock()
- 一系列同類函數,可加 MODULE_ 前綴,前綴單詞全大寫。如 SD 卡操做的系列函數,可爲 SD_PowerOnCard()、SD_PowerOffCard()
- 永遠不要使用 Tab 鍵(使用 4 個空格代替 Tab),須要以 4 個空格爲單位的縮進
- 換行符應使用 "unix"(LF),而不是windows(CR + LF)
- 文件結尾需空一行
不使用 K&R 風格花括號,左右括號都須要獨佔一行學習
局部變量定義應老是放在所在最小做用域(即最近的 內)裏的最前面,而且一行代碼僅定義一個變量ui
void MyFunctionName(void) { uint8_t myVariableName0; uint8_t myVariableName1; /* 代碼體 */ for (;;) { uint8_t myVariableName2; /* 代碼體 */ } }
代碼中全部無符號整型數字,均應加 "U" 後綴編碼
Hex: 0x1234ABCDU Dec: 1234U
僅使用 /* */ 來註釋
/* 註釋風格1,單獨佔一行 */ uint8_t i = 0; for (; i < 5;) { i++; /* 註釋風格2,與代碼共享一行 */ }
#endif 後面須要加以下注釋
#if MY_MACRO_NAME /* 代碼體 */ #endif /* MY_MACRO_NAME */
任何一個 .h 文件都須要包含下面格式的頭文件保護宏代碼,宏的命名與頭文件名保持一致。如文件名爲 hello_world.h,則宏名爲 _HELLO_WORLD_H_
#ifndef _HEADER_FILENAME_ #define _HEADER_FILENAME_ /* 頭文件內容 */ #endif /* _HEADER_FILENAME_ */
/* 包含頭文件代碼 */ #include "template.h" /******************************************************************************* * Definitions ******************************************************************************/ /* 私有(僅本源文件內使用)宏、枚舉、結構體的定義 */ #define MAX_DEVICES (128U) /******************************************************************************* * Variables ******************************************************************************/ /* 全部全局變量(外部,靜態,常量,指針)的定義 */ uint32_t g_deviceIndex = 0; static device_config_t s_deviceConfig; const uint32_t g_maxDevices = MAX_DEVICES; static volatile uint8_t *s_deviceData; /******************************************************************************* * Prototypes ******************************************************************************/ /* 內部函數(即 static 修飾)的聲明 */ static uint32_t GetDeviceIndex(void); /******************************************************************************* * Code ******************************************************************************/ /* 全部函數(外部,內部)的定義 */ void InitDevice(void) { s_deviceConfig.index = 1; s_deviceConfig.mode = kDeviceMode1; memset(s_deviceConfig.data, 5, sizeof(s_deviceConfig.data)); s_deviceConfig.isEnabled = true; } static uint32_t GetDeviceIndex(void) { return s_deviceConfig.index; } int main(void) { InitDevice(); g_deviceIndex = GetDeviceIndex(); while (1) { } }
/* * Copyright xxx * All rights reserved. * * xxx License * * Revision History: * v1.0 - Description */ #ifndef _TEMPLATE_H_ #define _TEMPLATE_H_ /* 包含頭文件代碼 */ #include <stdbool.h> #include <stdint.h> #include <string.h> /******************************************************************************* * Definitions ******************************************************************************/ /* 公共(可被其餘源文件使用)宏、枚舉、結構體的定義 */ enum _device_mode { kDeviceMode0 = 0x00U, kDeviceMode1 = 0x01U, kDeviceModeEnd = 0x02U, }; typedef struct _device_config { uint32_t index; uint32_t mode; uint8_t data[16]; bool isEnabled; } device_config_t; /* 外部全局變量的聲明 */ extern uint32_t g_deviceIndex; extern const uint32_t g_maxDevices; /******************************************************************************* * API ******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif /*_cplusplus*/ /* 外部函數(可加 extern 修飾)的聲明 */ void InitDevice(void); #if defined(__cplusplus) } #endif /*_cplusplus*/ #endif /* _TEMPLATE_H_ */
文章會同時發佈到個人 博客園主頁、CSDN主頁、微信公衆號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就能夠在手機上第一時間看了哦。