痞子衡嵌入式:知名半導體MCU大廠軟體開發C代碼規範

来源:https://www.cnblogs.com/henjay724/archive/2020/02/04/12259328.html
-Advertisement-
Play Games

今天要分享的這篇就是2013年痞子衡剛入職飛思卡爾半導體MCU軟體團隊時為了學習C編碼規範所翻譯的(外企嘛,各種資料都是洋文),當時飛思卡爾剛成立MCU軟體團隊不久,那時候Kinetis SDK也還沒有正式推出,整個團隊必須要有一個統一且良好的編碼風格,這樣寫出來的SDK才符合大廠身份。 ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是飛思卡爾軟體開發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主頁微信公眾號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • WPF提供了許多封裝項的集合的控制項,本章介紹簡單的ListBox和ComboBox控制項,後續哈會介紹更特殊的控制項,如ListView、TreeView和ToolBar控制項。所有這些控制項都繼承自ItemsControl類(ItemsControl類本身又繼承自Control類)。 ItemsContr ...
  • 微信公眾號: "Dotnet9" ,網站: "Dotnet9" ,問題或建議: "請網站留言" , 如果對您有所幫助: "歡迎贊賞" 。 少量代碼設計一個登錄界面 .NET CORE(C ) WPF開發 閱讀導航 1. 本文背景 2. 代碼實現 3. 本文參考 4. 源碼 1. 本文背景 繼續 Ma ...
  • 內容控制項不僅包括基本控制項,如標簽、按鈕以及工具提示;它們還包含特殊容器,這些容器可用於構造用戶界面中比較大的部分區域。 首先介紹ScrollViewer控制項,該控制項直接繼承自ContentControl類,提供了虛擬界面,允許用戶圍繞更大的元素滾動。與所有內容控制項一樣,ScrollViewer只能包 ...
  • 在Sublime Text3安裝目錄下新建一個文件 sublime_addright.inf 文件內容: [Version] Signature="$Windows NT$" [DefaultInstall] AddReg=SublimeText3 [SublimeText3] hkcr,"*\\s ...
  • " 返回《C 併發編程》" "1. 初始化共用資源" "2. Rx延遲求值" "3. 非同步數據綁定" "4. 非同步構造" "5. 非同步屬性" 1. 初始化共用資源 不管同時有多少線程調用 ,這個工廠委托只會運行一次,並且所有線程都等待同一個實例。 + 實例在創建後會被緩存起來,以後所有對 Value ...
  • 根據磁碟IO告警,找到占用磁碟IO (util)讀寫很高的進程。 ...
  • 硬鏈接(Hard Link)和軟鏈接也稱為符號鏈接(Symbolic Link)的目的是為瞭解決文件的共用使用問題。要闡明其原理,必須先理解Linux的文件存儲方式。 索引結點 Linux是一個UNIX類操作系統,所有類型的UNIX文件都是由操作系統通過索引節點來管理的。 索引節點是一個控制結構,包 ...
  • 當前情況下,經常會有需要到公司電腦進行一些操作,比如連接內網OA,資料庫或者提交文檔。為了減少外出,將使用frp進行內網穿透的方法進行一個說明。 前提條件 1. 一臺擁有公網 IP 的設備(如果沒有,伺服器可以使用https://diannaobos.com/frp/ 提供的免費伺服器) 2、需要遠 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...