天天看點

代碼風格(4)——格式一、總述二、行三、非ASCII字元四、空格還是制表位五、函數聲明與定義六、函數調用七、Lambda 表達式八、清單初始化格式九、條件語句十、循環和開關選擇語句十一、指針和引用表達式十二、布爾表達式十三、函數傳回值十四、預處理指令十五、類格式十六、構造函數初始值清單十七、命名空間格式化十八、水準留白十九、垂直留白二十、附錄

一、總述

每個人都可能有自己的代碼風格和格式,但如果一個項目中的所有人都遵循同一風格的話,這個項目就能更順利地進行。每個人未必能同意下述的每一處格式規則,而且其中的不少規則需要一定時間的适應,但整個項目服從統一的程式設計風格是很重要的,隻有這樣才能讓所有人輕松地閱讀和了解代碼。

二、行

2.1 行長度

每一行代碼字元數不超過

120

注釋行可以超過

120

個字元,但最大不超過

150

2.2 行寬度

函數體行寬原則上不超過

80

80

行限制事實上有助于避免代碼可讀性失控,比如超多重嵌套塊,超多重函數調用等等。

三、非ASCII字元

盡量不使用非

ASCII

字元,使用時必須使用

UTF-8

編碼。

即使是英文,也不應将使用者界面的文本寫死到源代碼中,是以非 ASCII 字元應當很少被用到。特殊情況下可以适當包含此類字元。例如,代碼分析外部資料檔案時,可以适當寫死資料檔案中作為分隔符的非 ASCII 字元串;更常見的是 (不需要本地化的) 單元測試代碼可能包含非 ASCII 字元串。此類情況下,應使用 UTF-8 編碼,因為很多工具都可以了解和處理

UTF-8

編碼。

四、空格還是制表位

隻使用空格,每次縮進

4

個空格。(使用記事本打開檢查是否使用空格還是制表符)

如果要在代碼中使用制表符。你應該設定編輯器将制表符轉為空格。

五、函數聲明與定義

傳回類型和函數名在同一行,參數也盡量放在同一行,如果放不下就對形參分行,分行方式如下

六、函數調用

一緻。

函數看上去像這樣:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) 
{
    DoSomething();  // 4 space indent
    ...
}
           

如果同一行文本太多,放不下所有參數:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
                                             Type par_name3) 
{
    DoSomething();  // 4 space indent
    ...
}
           

甚至連第一個參數都放不下:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
        Type par_name1,  // 8 space indent
        Type par_name2,
        Type par_name3) 
{
    DoSomething();  // 4 space indent
    ...
}
           
注意以下幾點:
  • 使用好的參數名。
  • 隻有在參數未被使用或者其用途非常明顯時,才能省略參數名。
  • 如果傳回類型和函數名在一行放不下,分行。
  • 如果傳回類型與函數聲明或定義分行了,不要縮進。
  • 左圓括号總是和函數名在同一行。
  • 函數名和左圓括号間永遠沒有空格。
  • 圓括号與參數間沒有空格。
  • 左大括号

    另起新行

  • 右大括号總是單獨位于函數

    最後一行

  • 所有形參應盡可能對齊。
  • 預設縮進為 4 個空格。
  • 換行後的參數保持 8 個空格的縮進。或盡量對齊上一行參數。

屬性,和展開為屬性的宏,寫在函數聲明或定義的最前面,即傳回類型之前:

六、函數調用

要麼一行寫完函數調用,要麼在圓括号裡對參數分行,要麼參數另起一行且縮進

8

格。如果沒有其它顧慮的話,盡可能精簡行數,比如把多個參數适當地放在同一行裡。

函數調用遵循如下形式:

如果同一行放不下,可斷為多行,後面每一行都和第一個實參對齊,左圓括号後和右圓括号前不要留白格:

bool retval = DoSomething(averyveryveryverylongargument1,
                          argument2, argument3);
           

參數也可以放在次行,縮進8格:

if(...) 
{
    DoSomething(
        argument1, argument2,  // 8 空格縮進
        argument3, argument4);
}
           

七、Lambda 表達式

Lambda 表達式對形參和函數體的格式化和其他函數一緻;捕獲清單同理,表項用逗号隔開。

若用引用捕獲,在變量名和

&

之間不留白格。

int x = 0;
auto add_to_x = [&x](int n) { x += n; };
           

短 lambda 就寫得和内聯函數一樣。

std::set<int> blacklist = {7, 8, 9};
std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
digits.erase(std::remove_if(digits.begin(), digits.end(), [&blacklist](int i) 
{
    return blacklist.find(i) != blacklist.end();
}), digits.end());
           

八、清單初始化格式

如果清單初始化伴随着名字,比如類型或變量名,格式化時将将名字視作函數調用名,{} 視作函數調用的括号。如果沒有名字,就視作名字長度為零。

// 一行清單初始化示範.
return {foo, bar};
functioncall({foo, bar});
pair<int, int> p{foo, bar};

// 當不得不斷行時.
SomeFunction(
    {"assume a zero-length name before {"},  // 假設在 { 前有長度為零的名字.
    some_other_function_parameter);

SomeType variable
{
    some, other, values,
    {"assume a zero-length name before {"},  // 假設在 { 前有長度為零的名字.
    SomeOtherType
    {
        "Very long string requiring the surrounding breaks.",  // 非常長的字元串, 前後都需要斷行.
        some, other values
    },
    SomeOtherType
    {
        "Slightly shorter string",  
        some, other, values
    }
};

SomeType variable
{
    "This is too long to fit all in one line"
};  

MyType m = 
{  
    superlongvariablename1,
    superlongvariablename2,
    {short, interior, list},
    {
        interiorwrappinglist,
        interiorwrappinglist2
    }
};
           

九、條件語句

9.1 if語句格式

if(condition)  // '('左邊和後邊都沒有空格,')'左邊沒有空格
{              // '{'換行
    ...        // 4 空格縮進
}
else           // else 換行  
{  
    ...
}
           

如果能增強可讀性,簡短的條件語句允許寫在同一行。隻有當語句簡單并且沒有使用

else

子句時使用:

if(x == kFoo) return new Foo();
if(x == kBar) return new Bar();
           

但最好還是使用大括号:

if(x == kFoo)
{
    return new Foo();
}
           

如果語句有

else

分支則不允許:

// 不允許 - 當有 ELSE 分支時 IF 塊卻寫在同一行
if (x) DoThis();
else DoThat();
           

9.2 布爾變量與零值比較

不可将布爾變量直接與 TRUE、FALSE 或者 1、0 進行比較。

根據布爾類型的語義,零值為“假”(記為 FALSE),任何非零值都是“真”(記為TRUE)。TRUE 的值究竟是什麼并沒有統一的标準。例如 Visual C++ 将 TRUE 定義為1,而 Visual Basic 則将 TRUE 定義為 -1。

假設布爾變量名字為 flag,它與零值比較的标準 if 語句如下:

if (flag) // 表示 flag 為真

if (!flag) // 表示 flag 為假

其它的用法都屬于不良風格,例如:

if (flag == TRUE)

if (flag == 1)

if (flag == FALSE)

if (flag == 0)

9.3 浮點變量與零值比較

不可将浮點變量用“==”或“!=”與任何數字比較。

千萬要留意,無論是 float 還是 double 類型的變量,都有精度限制。是以一定要避

免将浮點變量用“==”或“!=”與數字比較,應該設法轉化成“>=”或“<=”形式。

假設浮點變量的名字為 x,應當将

if(x == 0.0) // 隐含錯誤的比較

轉化為

if((x>=-EPSINON) && (x<=EPSINON))

其中 EPSINON 是允許的誤差(即精度)。

9.4 指針變量與零值比較

應當将指針變量用“==”或“!=”與 NULL 比較。

指針變量的零值是“空”(記為 NULL)。盡管 NULL 的值與 0 相同,但是兩者意義不

同。假設指針變量的名字為 p,它與零值比較的标準 if 語句如下:

if(p == NULL) // p 與 NULL 顯式比較,強調 p 是指針變量

if(p != NULL)

不要寫成

if(p == 0) // 容易讓人誤解 p 是整型變量

if (p != 0)

或者

if(p) // 容易讓人誤解 p 是布爾變量

if(!p)

十、循環和開關選擇語句

switch

語句可以使用大括号分段,以表明 cases 之間不是連在一起的。在單語句循環裡,括号可用可不用。空循環體應使用

{}

continue

switch

語句中的

case

塊可以使用大括号也可以不用,取決于你的個人喜好。如果用的話,要按照下文所述的方法。

如果有不滿足

case

條件的枚舉值,

switch

應該總是包含一個

default

比對 (如果有輸入值沒有 case 去處理, 編譯器将給出 warning)。如果

default

應該永遠執行不到,簡單的加條

assert

switch(var)  // '('左邊和右邊沒有空格,')'左邊沒有空格
{
case 0:  // 無空格
    { 
        ...      // 8 空格縮進
        break;
    }
case 1: 
    {
        ...
        break;
    }
default: 
    assert(false);
}
           

循環語句:

for(int i = 0; i < kSomeNumber; ++i) 
{
    printf("I take it back\n");
}
           

空循環體應使用

{}

continue

,而不是一個簡單的分号。

while(condition) 
{
    // 反複循環直到條件失效.
}
for(int i = 0; i < kSomeNumber; ++i)  // 可 - 空循環體.
{
} 
while(condition) continue;  // 可 - contunue 表明沒有邏輯.
           

十一、指針和引用表達式

句點或箭頭前後不要有空格。指針/位址操作符 (

*, &

) 之後不能有空格。

下面是指針和引用表達式的正确使用範例:

x = *p;
p = &x;
x = r.y;
x = r->y;
           

注意:

  • 在通路成員時,句點或箭頭前後沒有空格。
  • 指針操作符

    *

    &

    後沒有空格。

在聲明指針變量或參數時,星号與類型或變量名緊挨都可以:

// 好, 空格前置,推薦使用
char *c;
const string &str;

// 好, 空格後置.
char* c;
const string& str;
           
int x, *y;  // 不允許 - 在多重聲明中不能使用 & 或 *
char * c;  // 差 - * 兩邊都有空格
const string & str;  // 差 - & 兩邊都有空格.
           

在單個檔案内要保持風格一緻,是以,如果是修改現有檔案,要遵照該檔案的風格。

十二、布爾表達式

如果一個布爾表達式超過

标準行寬 120個字元

,斷行方式要統一一下。

下例中,邏輯與 (

&&

) 操作符總位于行尾:

if(this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another && last_one) 
{
    ...
}
           

注意,上例的邏輯與 (

&&

) 操作符均位于行尾。

十三、函數傳回值

不要在

return

表達式裡加上非必須的圓括号。

隻有在寫

x = expr

要加上括号的時候才在

return expr

;裡使用括号。

return result;                  // 傳回值很簡單, 沒有圓括号.
// 可以用圓括号把複雜表達式圈起來, 改善可讀性.
return (some_long_condition &&
        another_condition);
           
return (value);                // 差 - 畢竟您從來不會寫 var = (value);
return(result);                // 差 - return 可不是函數!
           

十四、預處理指令

預處理指令不要縮進,從行首開始。

即使預處理指令位于縮進代碼塊中,指令也應從行首開始。

// 好 - 指令從行首開始
    if(lopsided_score) 
    {
#if DISASTER_PENDING      // 正确 - 從行首開始
        DropEverything();
# if NOTIFY               // 非必要 - # 後跟空格
        NotifyClient();
# endif
#endif
    BackToNormal();
    }
           
// 差 - 指令縮進
    if (lopsided_score) 
    {
        #if DISASTER_PENDING  // 差 - "#if" 應該放在行開頭
        DropEverything();
        #endif                // 差 - "#endif" 不要縮進
        BackToNormal();
    }
           

十五、類格式

通路控制塊的聲明依次序是

public:

protected:

private:

,每個都縮進 2 個空格。

class MyClass : public OtherClass 
{
  public:      // 注意有2個空格的縮進
    MyClass();  // 标準的4空格縮進
    explicit MyClass(int var);
    ~MyClass() {}

    void SomeFunction();
    void SomeFunctionThatDoesNothing() {}

    void set_some_var(int var) { some_var_ = var; }
    int some_var() const { return some_var_; }

  private:
    bool SomeInternalFunction();

    int some_var_;
    int some_other_var_;
};
           

注意事項:

  • 所有基類名應在 80 列限制下盡量與子類名放在同一行。
  • 關鍵詞

    public:

    protected:

    private:

    要縮進 1 個空格。
  • 除第一個關鍵詞 (一般是

    public

    ) 外,其他關鍵詞前要空一行。如果類比較小的話也可以不空。
  • 這些關鍵詞後不要保留白行。
  • public

    放在最前面,然後是

    protected

    ,最後是

    private

十六、構造函數初始值清單

構造函數初始化清單放在同一行或按8格縮進并排多行。

// 如果所有變量能放在同一行:
MyClass::MyClass(int var) : some_var_(var) 
{
    DoSomething();
}

// 如果不能放在同一行,
// 必須置于冒号後, 并縮進 4 個空格
MyClass::MyClass(int var)
        : some_var_(var), some_other_var_(var + 1) 
{
    DoSomething();
}

// 如果初始化清單需要置于多行, 将每一個成員放在單獨的一行
// 并逐行對齊
MyClass::MyClass(int var)
        : some_var_(var),             // 8 space indent
        some_other_var_(var + 1) 
{ 
    DoSomething();
}

// 右大括号 } 可以和左大括号 { 放在同一行
// 如果這樣做合适的話
MyClass::MyClass(int var)
        : some_var_(var) {}
           

十七、命名空間格式化

命名空間内容不縮進。

命名空間不要增加額外的縮進層次,例如:

namespace 
{
void foo()  // 正确. 命名空間内沒有額外的縮進. 
{ 
    ...
}

}  // namespace
           

不要在命名空間内縮進:

namespace
{
  // 錯, 縮進多餘了.
    void foo() 
    {
        ...
    }
}  // namespace
           

聲明嵌套命名空間時,每個命名空間都獨立成行。

namespace foo {
namespace bar {
           

十八、水準留白

18.1 通用

水準留白的使用根據在代碼中的位置決定。永遠不要在行尾添加沒意義的留白。

void f(bool b)  
{  
    ...
    int i = 0;  // 分号前不加空格.
    // 清單初始化中大括号内的空格是可選的.
    // 如果加了空格, 那麼兩邊都要加上.
    int x[] = { 0 };
    int x[] = {0};

    // 繼承與初始化清單中的冒号前後恒有空格.
class Foo : public Bar 
{
  public:
    // 對于單行函數的實作, 在大括号内加上空格
    // 然後是函數實作
    Foo(int b) : Bar(), baz_(b) {}  // 大括号裡面是空的話, 不加空格.
    void Reset() { baz_ = 0; }  // 用括号把大括号與實作分開.
    ...
           

18.2 循環和條件語句

if(b)   // 圓括号内部不緊鄰空格.
{          
} 
else 
{          
}
while(test) {}  
switch(i) 
{
    for(int i = 0; i < 5; ++i) 
    {
        switch(i) 
        {    
            if(test) 
            {   
                for(int i = 0; i < 5; ++i) 
                {
                    for( ; i < 5 ; ++i)   // 循環裡内 ; 後恒有空格, ;  前可以加個空格.
                    {  
                        switch(i) 
                        {
                        case 1:         // switch case 的冒号前無空格.
                            ...
                        case 2: 
                            break;  
           

18.3 操作符

// 指派運算符前後總是有空格.
x = 0;

// 其它二進制操作符也前後恒有空格, 不過對于表達式的子式可以不加空格.
// 圓括号内部沒有緊鄰空格.
v = w * x + y / z;
v = w*x + y/z;
v = w * (x + z);

// 在參數和一進制操作符之間不加空格.
x = -5;
++x;
if(x && !y)
  ...
           

18.4 模闆和轉換

// 尖括号(< and >) 不與空格緊鄰, < 前沒有空格, > 和 ( 之間也沒有.
vector<string> x;
y = static_cast<char *>(x);

// 在類型與指針操作符之間留白格也可以, 但要保持一緻.
vector<char *> x;
           

十九、垂直留白

這不僅僅是規則而是原則問題了:不在萬不得已,不要使用空行。尤其是:兩個函數定義之間的空行不要超過 2 行,函數體首尾不要留白行。函數體中也不要随意添加空行。

基本原則是:同一屏可以顯示的代碼越多,越容易了解程式的控制流。當然,過于密集的代碼塊和過于疏松的代碼塊同樣難看,這取決于你的判斷。但通常是垂直留白越少越好。

下面的規則可以讓加入的空行更有效:

  • 用于差別概念層次,如函數體内變量定義與調用函數用空行區分開。
  • 在多重 if-else 塊裡加空行或許有點可讀性。

19.1 概念間垂直方向上的區隔

幾乎所有的代碼都是

從上往下

讀,

從左往右

讀。每行展現一個表達式或一個子句,每組代碼行展示一條完整的思路。這些思路用空白行區隔開來。

如下。在封包聲明/導入聲明和每個函數之間,都有空白行隔開。這條極其簡單的規則極大地影響到代碼的視覺外觀。每個空白行都是一條線索,辨別出新的獨立概念。往下讀代碼,你的目光總會停留于空白行之後那一行。

package fitnesse.wikitext.widgets;

import java.util.regex.*;

public class BoldWidget extends ParentWidget {
  public static final String REGEXP = "'''.+?'''";
  private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
    Pattern.MULTILINE + Pattern.DOTALL
  );

  public BoldWidget(ParentWidget parent, String text) throws Exception {
    super(parent);
    Matcher match = pattern.matcher(text);
    match.find();
    addChildWidgets(match.group(1));
  }

public String render() throws Exception {
  StringBuffer html = new StringBuffer("</b>");
  return html.toString();
  }
}  
           

如下。抽掉這些空白行,代碼可讀性減弱了不少。

package fitnesse.wikitext.widgets;
import java.util.regex.*;
public class BoldWidget extends ParentWidget {
  public static final String REGEXP = "'''.+?'''";
  private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
    Pattern.MULTILINE + Pattern.DOTALL
  );
  public BoldWidget(ParentWidget parent, String text) throws Exception {
    super(parent);
    Matcher match = pattern.matcher(text);
    match.find();
    addChildWidgets(match.group(1));
  }
public String render() throws Exception {
  StringBuffer html = new StringBuffer("</b>");
  return html.toString();
  }
}  
           

在你不特意注視時,後果就更嚴重了。在第一個例子中,代碼組會跳到你眼中,而第二個例子就像一堆亂麻。兩段代碼的差別,展示了垂直方向上區隔的作用。

二十、附錄

20.1 .c檔案

/**===========================================================================
  Copyright (C) XXX Technologies Co., Ltd. All rights reserved.

  @file     user_udp.c
  @brief    本檔案用于UDP通訊接口
  @author   Leung Man-Wah
  @version  r0.1
  @date     2019/07/04
  @license XXX
----------------------------------------------------------------------------
  Remark: (備注描述)
----------------------------------------------------------------------------
                                History
----------------------------------------------------------------------------
  <Date>     | <Version> | <Author>       | <Description>
-------------|-----------|----------------|---------------------------------
  2019/07/04 | r0.1      | Leung Man-Wah  | 建立
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
============================================================================*/

/*********************************************************************
 * INCLUDES
 */
// 系統/協定棧/庫頭檔案(使用時去掉此行注釋)
#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"

// 自定義頭檔案(使用時去掉此行注釋)
#include "user_udp.h"
#include "user_httpserver.h"
#include "cJSON.h"
#include "wb_protocol.h"
#include "common.h"

// 靜态函數聲明(使用時去掉此行注釋)
static void udpDeviceInfoEspconn(void);
static void udpBleDataEspconn(void);
static void udpSendDataCallback(void *arg);

/*********************************************************************
 * CONSTANT
 */
const uint16 UDP_DEV_INFO_PERIOD = 1000;

/*********************************************************************
 * GLOBAL VARIABLES
 */
uint8 g_bleDeviceRssiStandrdValue = BLE_DEV_RSSi_DEFAULT_VALUE;
bool g_httpClientConnectCloudFlag = false;										    // 聯網标志,0 - 斷網;1 - 聯網
bool g_httpClientHeartbeatFlag = false;											    // 心跳标志,0 - 非發心跳中;1 - 發心跳中
uint8 g_httpClientRenewalRecordFlag = 0;										    // 續傳标志,0 - 非續傳中;1 - 續傳中;>=2 - 續傳失敗

/*********************************************************************
 * LOCAL VARIABLES
 */
static struct espconn s_devInfoUdpEspconn;											// 裝置資訊UDP廣播結構體
static struct espconn s_bleDataUdpEspconn;											// 藍牙資料UDP廣播結構體
static os_timer_t s_udpDevInfoTimer;												// UDP廣播裝置資訊的定時器
static uint8 s_udpDevInfoSendCount;													// UDP廣播裝置資訊次數

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
/**
 @brief UDP通訊初始化
 @param 無
 @return 無
*/
void UdpInit(void)
{
	udpDeviceInfoEspconn();
	udpBleDataEspconn();
}

/*********************************************************************
 * LOCAL FUNCTIONS
 */
/**
 @brief UDP發送繼電器狀态
 @param deviceType -[in] 裝置類型
 @param pMacAddr -[in] MAC位址
 @param relayStatus -[in] 繼電器狀态
 @return 無
*/
static void udpSendRelayStatus(uint8 deviceType, uint8 *pMacAddr, uint8 relayStatus)
{
	char sendData[UDP_SEND_BUFFER_SIZE] = {0};

	jsonPackageRelayStatus(sendData, deviceType, pMacAddr, relayStatus);

	espconn_send(&s_devInfoUdpEspconn, sendData, strlen(sendData));					// UDP發送資料
}

/****************************************************END OF FILE****************************************************/

           

20.2 .h檔案

/**===========================================================================
  Copyright (C) XXX Technologies Co., Ltd. All rights reserved.

  @file     user_udp.h
  @brief    本檔案用于UDP通訊接口
  @author   Leung Man-Wah
  @version  r0.1
  @date     2019/07/04
  @license XXX
----------------------------------------------------------------------------
  Remark: (備注描述)
----------------------------------------------------------------------------
                                History
----------------------------------------------------------------------------
  <Date>     | <Version> | <Author>       | <Description>
-------------|-----------|----------------|---------------------------------
  2019/07/04 | r0.1      | Leung Man-Wah  | 建立
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
-------------|-----------|----------------|---------------------------------
             |           |                |
============================================================================*/

#ifndef _USER_UDP_H_
#define _USER_UDP_H_

/*********************************************************************
 * INCLUDES
 */

/*********************************************************************
 * DEFINITIONS
 */
#define UDP_JSON_ERROR				0x00
#define UDP_START_SEND_DEV_INFO		0x01
#define UDP_STOP_SEND_DEV_INFO		0x02
#define UDP_CONFIG_CLOUD_ERROR		0x03
#define UDP_SEND_RELAY_STATUS		0x04
#define UDP_RESTART_SEND_DEV_INFO	0x05
#define UDP_RESEND_RELAY_STATUS		0x06

#define DEV_TYPE_BLE				0x01
#define DEV_TYPE_WIFI				0x02

#define UDP_SEND_BUFFER_SIZE 		1024

/*********************************************************************
 * TYPEDEFS
 */
typedef struct
{
    uint8 devkey[40];
    uint8 token[40];
    uint8 activeStatus;
    ip_addr_t tcpServerIp;
    uint16 tcpServerPort;
    char tcpServerDomain[32];
    ip_addr_t httpServerIp;
	uint16 httpServerPort;
	char httpServerDomain[32];
	char httpServerPath[32];
	ip_addr_t dhcpIp;
	ip_addr_t dhcpNetmask;
	ip_addr_t dhcpGateway;
	uint8 dhcpFlag;
    uint8 bleDeviceRssiStandrdValue;
    uint8 productType;
} FlahSavedParam_t;

/*********************************************************************
 * GLOBAL VARIABLES
 */
extern uint8 g_bleDeviceRssiStandrdValue;
extern bool g_httpClientConnectCloudFlag;						
extern bool g_httpClientHeartbeatFlag;									
extern uint8 g_httpClientRenewalRecordFlag;										 

/*********************************************************************
 * API FUNCTIONS
 */
void UdpInit(void);
void UdpSendDeviceInfo(void);
void UdpSendRelayStatus(uint8 deviceType, uint8 *pMacAddr, uint8 relayStatus);
void UdpSendBleScanData(uint8 *pSendData);

#endif /* _USER_UDP_H_ */
           

• 由 Leung 寫于 2019 年 10 月 30 日

• 參考:Google 開源項目風格指南——9. 格式

    [代碼整潔之道]

繼續閱讀