嵌入式 C 編碼風格
版本 | 日期 | 作者 | 備註 |
---|---|---|---|
V1.0 | 2019.09.16 | Like Shadows | 初版 |
文件頭
-
所有新建的文件,都必須在最開始聲明 Project 的許可條款。
-
對於從其它地方拷貝的文件,如果有許可條款聲明,則應保留。
Project 的許可條款示例如下:
/* * Copyright [2019] [xxxx Co., Ltd] * * Licensed under the Apache License, Version 2.0 (the "License"), * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.xxxx.com * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */
空格和括號
-
代碼必須以 4 字節縮進,不建議採用 TAB 縮進。
-
不允許在行尾添加空格。
-
關鍵字後面需要添加空格 (如:for,if,return,switch,while)。
-
for,else,if,while,表達式必須使用大括號
//正確 if (x) { assert(0); } else { assert(0); } //錯誤 if (x) assert(0); else assert(0);
-
表達式的括號必須與表達式位於同一行。
//正確 for (i = 0; i < 10; i ++) { if (i == 5) { break; } else { continue; } } //錯誤 for (i = 0; i < 10; i ++) { if (i == 5) { break; } else { continue; } }
-
函數聲明之後,括號必須位於下一行的起始位置。
//正確 static void * function(int var1, int var2) { } //錯誤 static void * function(int var1, int var2) { }
行長度和換行規則
-
每行最長不應該超過 79 字符長度。
-
當需要換行封裝表達式時,操作符應位於行尾。
//正確 if (x && y == 10 && b) //錯誤 if (x && y == 10 && b)
註釋
-
註釋
文件頭
。/** * @file xxx.h * @brief 文件簡單概述 * * 詳細概述 * * @author 作者 * @version 版本號(maj.min 主版本.次版本格式) * @date 日期 */
-
註釋
函數
。/** * @brief 函數的簡單概述 * @return 函數返回值,不同值表示的含義 * @note 函數需要注意的事項 * @param para1 IN/OUT 參數 para1 是輸入輸出參數 * @param para2 IN 參數 para2 是輸入參數 */
-
註釋
變量/枚舉
。int a; ///< 變量 a 的說明 /// @brief xxx 枚舉變量的簡要說明 /// /// xxx 枚舉變量的詳細說明,枚舉變量的詳細說明和函數的說明寫法一致, /// 每個枚舉變量可以進行單獨說明 enum { em1, ///< 枚舉值 em1 的說明 em2 };
-
所有的公用 APIs 的註釋必須使用 Doxygen 的註釋規範來描述目的,參數和返回值等等。私有 APIs 則不需要。
頭文件
-
頭文件必須包含以下結構:
- Project 的許可條款 (參見文件頭部分)。
#ifdef
,用於防止多重包含。#include
,用於引用要求包含的其他頭文件。#ifdef __cplusplus
,用於爲 C++ 封裝友好的 APIs。- 頭文件的內容。
#ifdef
,將使用以下格式,如果目錄名爲os
,文件名爲callout.h
,則定義如下:
```c #ifndef _OS_CALLOUT_H #define _OS_CALLOUT_H ... #endif ```
-
#include
,必須位於#ifdef __cplusplus
之前。 -
cplusplus
必須使用以下格式,並且位於頭文件內容之前。#ifdef __cplusplus extern "C" { #endif ... /* content */ #ifdef __cplusplus } #endif
命名
-
函數,結構體和變量的名稱必須全部小寫。
-
名稱應該儘可能的短,但也不能太短。
-
全局可見的名稱應該加上模塊名稱作爲前綴,並以
_
相連接。/* os 爲模塊名, callout_int 爲函數名 */ //正確 os_callout_int(&c); //錯誤 callout_int(&c);
函數
-
函數調用時,函數名後面不能有空格。
//正確 rc = function(a); //錯誤 rc = function (a);
-
函數的參數見應使用
,
和空格分隔開來。//正確 rc = function(a, b); //錯誤 rc = function(a,b);
-
函數類型應位於函數名的上一行,並獨佔一行。
//正確 static void * function(int var1, int var2) { } //錯誤 static void *function(int var1, int var2) { }
-
如果函數返回成功或者錯誤,一般而言,使用
0
代表成功,!0
代表失敗。
變量和宏
- 不要使用
typedef
重定義結構體。這會讓應用程序使用指針訪問這些結構體變得不透明。 typedef
可以用在簡單數據類型,可以有效的隱藏底層使用的類型或爲其起個別名 (如:os_time_t
)。通過添加後綴_t
來標記它們使用了typedef
重定義了。- 將函數的所有局部變量定義放在函數體最前面,應位於任何語句或表達式之前。
編譯
- 代碼編譯必須使用
-Wall
參數進行乾淨的編譯。