C/C++语言编程规范

友情链接:C/C++系列系统学习目录

在这里插入图片描述

各位读者你们好,本篇作为本基础专栏的第一篇,我并不打算直接开始梳理基础知识点
 
首先我们应该学习并且养成良好习惯的是:
 
C/C++语言编程规范⛳⛳⛳



🚀前言

首先要清楚:代码阅读的次数远远多于代码编写的次数。我们所编写的代码更侧重于阅读方便而不是编写方便。

在C和C++的编程中,编写代码不只是为了实现功能而写代码,写代码是软件实现功能,也是一种可维护、易于维护的工作,而且是一种艺术。

如果一个程序员写的代码只是为了实现功能,没有注释,代码变量的命名乱七八糟,除了自己能看懂,有的人写的代码自己过了一段时间也看不懂,对于后续代码软件功能的维护,不可行。这样的代码就是垃圾代码,哪怕你当时很快实现了这一功能需求。那么也只是废码。因为不易于后续别人的维护和可移植。

 

🚀一、基本准备工作

 

⛳(一)设计工程目录结构

1、工程本身的文件、项目编译生成的中间文件放一个文件夹;

2、最终生成的目标文件单独放一个文件夹;

3、如果有工程依赖的库文件等单独放一个文件夹;

4、用户代码文件放单独一个文件夹,或者将头文件和源文件单独分开放置;

5、用户代码文件里面如果有比较重要的功能模块单独放一个文件夹,如陀螺仪,气压计,光感,音乐,灯效,图片,字库等。

6、重要的项目资料单独放一个文件夹保存,如硬件原理图,软件框架图,通信协议,复杂重要功能的说明等等。

7、必须维护一个软件版本升级记录文档,也可以在某个主要的代码文件内维护(不推荐)。

8、可以为一些代码阅读工具需要的生成文件开一个文件夹,如SourceInsight。
 

⛳(二)版权和版本的申明

1、基本原则:

位置:位于说明文件或者源文件头部,或者源文件和头文件都加上版本声明。

内容:版权、文件名,概要;版本号-作者-日期+代码更新信息,备注信息等等;

2、举例:

(1)简单版本申明

在这里插入图片描述
(2)头文件注释带上函数功能的简要说明,但如果在头文件有对外接口的函数声明,则在函数声明上进行函数功能的注释。

在这里插入图片描述
(3)源文件,说明此模块功能,主要函数,被其他函数调用的接口

在这里插入图片描述
(4)源文件和头文件都加上版本声明

STM32F10x_FWLib / stm32f10x_adc.h
/********************************************************************************
  * @file    stm32f10x_adc.h
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    11-March-2011
  * @brief   This file contains all the functions prototypes for the ADC firmware
  *          library.
  ******************************************************************************
  * @attention
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  ******************************************************************************
  */
  
STM32F10x_FWLib / stm32f10x_adc.c
 /********************************************************************************
  * @file    stm32f10x_adc.c
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    11-March-2011
  * @brief   This file provides all the ADC firmware functions.
  ******************************************************************************
  * @attention
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  ******************************************************************************  
  */

 

🚀二、布局和排版规则

 

⛳(一)头文件布局

1、头文件开头处的版权和版本声明。

2、预处理块:

#ifndef/#def/#endif 防止头文件被重复引用。

3、其他头文件

#include <filename.h> :(系统头文件)引用标准库的头文件,编译器将从标准库目录开始搜索。
#include “filename.h”: (项目头文件)引用非标准库的头文件,编译器从用户的工作目录开始搜索。

4、函数和类结构声明等

(1)宏定义等
(2)函数,头文件只存声明,不存定义。
(3)类结构声明

#ifndef   GRAPHICS_H	// 防止graphics.h被重复引用
#define   GRAPHICS_H

#include <math.h>		// 引用标准库的头文件#include "myheader.h"	// 引用非标准库的头文件void Function1();		// 全局函数声明class Box				// 类结构声明
{};
#endif

5、extern规范用法:

(1)不提倡用全局变量,不用extern int value; 这类声明;
(2)必须使用时,要规范用法。不要在一个源文件中直接用extern调用另个一文件的变量。而是:在1.h头文件中声明extern int value;在2.h里面包含1.h用来调用value。

 

⛳(二)源文件布局

1、 定义文件开头处的版权和版本声明。

2、 对一些头文件的引用。

3、 程序的实现体。

// 版权和版本声明见前面图片示例,此处省略。
#include "graphics.h"     // 引用头文件// 全局函数的实现体
void Function1()
{}

// 类成员函数的实现体
void Box::Draw()
{}

 

⛳(三)排版和代码行基本规则

目的:使代码布局整齐清晰,便于阅读和理解。

1、起始代码的缩进:

函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格, case语句下的情况处理语句也要遵从语句缩进要求。

2、缩进规则:

(1)缩进风格:程序块要采用缩进编写,缩进的空格数一般为4个。
(2)不用TAB用空格:以免用不同的编辑器阅读程序时,因 TAB 键所设置的空格数目不同而造成程序布局不整齐。

3、程序块大括号对齐:

(1)WIN和嵌入式底层:程序分界符" {"和“ }”:应该独占一行并且两者位于同一列,同时与引用他们的语句左对齐;
(2)linux:‘{’位于上一行的行末,此时‘}’与‘{’所在行的行首对齐,‘{’前至少有一个空格。
(3)循环格式

//多在linux底层和linux应用编程,单片机嵌入式未见此种用法。
for (...) { 
   ... // program code
} 

//windows一般统一用下面这个格式。。。
for (...) 
{
... // program code
}

4、空行:

每个函数定义结束后,相对独立的程序块之间(逻辑密切除外)、变量说明和程序块中间之后必须加空行。

5、标志符语句独占一行:

if、 for、 do、 while、 case、 switch、 default等语句自占一行,不论语句的执行语句部分无论多少都要加括号{}。

6、长句拆分:

(1)单行单语句,一行不超过一个语句:
不允许把多个短语句写在一行中,即一行只写一条语句。
(2)语句的拆分:
代码长度最好控制在70-80个字符以内,较长的语句( >80字符)要分成多行书写。

函数或过程中的参数较长,循环、判断等语句中有较长的表达式或语句,要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

//【1】
    report_or_not_flag = ((taskno < MAX_ACT_TASK_NUMBER)

                       && (n7stat_stat_item_valid (stat_item))

                       && (act_task_table[taskno].result_data != 0));

//【2】
    for (i = 0, j = 0; (i < BufferKeyword[word_index].word_length)

                  && (j < NewKeyword.word_length); i++, j++)

//【3】 
        CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) |

                                             ((uint32_t)TxMessage->Data[2] << 16) |

                                             ((uint32_t)TxMessage->Data[1] << 8) |

                                             ((uint32_t)TxMessage->Data[0]));

7、代码行内的空格和修饰符、括号等:

(1)关键字后留空格:C语言的32个关键字,如if/while/do/case ();

if (NewState != DISABLE)

(2)函数名后不留空格:紧跟括号( , 区别关键字.

void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);

(3)紧跟:(号向后紧跟, )和,和;向前紧跟,不留空格; int a, b, c;

(4)二元操作符:前后加空格;==对等操作

(5)一元操作符:前后不加空格;如"[ ]“和” . “和”->"这类操作符前后不加空格.==关系密切的立即操作符

(6)对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格:

if ((a>=b) && (c<=d))      // 良好的风格
    for (i=0; i<10; i++)      // 良好的风格
        x = a<b ? a:b;        // 良好的风格

(7)修饰符紧靠变量名:不会被误认: int *x, y;

(8)注意运算符的优先级,并用括号明确表达式的操作顺序:

 if ((a | b) < (c & d))
     if ((a>=b) && (c<=d))      // 良好的风格

(9)特别注意:

【1】变量定义规则:

每个变量定义时同时进行初始化
每个变量定义单独占一行
对每个变量的作用进行注释

int n = 0;//表示个数
int I = 1;//循环控制变量
float fvalue = 0;//值

【2】二元运算符前后各空一格

number >= 0;
k = m + n;

【3】在模块之间要空一行,在return 语句前也要空一行。但不能有太多空行。

【4】不写复杂的语句,一行代码只做一件事情。

比如:最好将

int x=y+z,k=m+n;

写成2句,如下:

int x = y + z;
int k = m + n;

【5】if、else、elseif、for、do、while、case等语句最好单独占一行。

【6】每个语句块不管代码多少,都加上{},

例如:

if ( x >= 0)
{
    k = m + n;
}

int iSum = 0;
int i = 0;

for ( i = 1; I < 20; i++)
{
	iSum = iSum + i;
}

【7】长行拆分。太长的代码行最好拆分成几个短的代码行,最好不要超过一行(即80个字符)。

【8】对齐与缩进。严格采用阶梯层次组织程序代码, 各层次缩进的分格采用VC的缺省风格,即每层次缩进为4格,括号位于下一行,要求相匹配的大括号在同一列,对继行则要求再缩进4格。

 

🚀三、注释规则

注释规则:对程序功能、变量作用、重要的语句或语句块、重要模块的功能、函数及接口进行简明扼要的说明

目的:增加代码的可读性,帮助更好的理解程序。

(一)必要性:

在代码的功能、意图层次上注释,解释代码的目的、功能和采用的方法,提供代码外的信息,帮助理解,已经清楚的语句就不要重复注释。

说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。

(二)及时性和准确性:

边写代码边注释,改了代码也要改注释,不用的注释要删除。

(三)自注释:

通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构。

说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。

(四)注释格式和语言尽量统一:

1、格式尽量统一用/* */。
2、格式如果不能非常流利准确用英文表达,则统一用中文,不要中英文混用。

说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。

(五)注释所在位置和排版:

1、注释放在语句上方或者右方不放在下方,注释放在上方时必须和上面的代码用空行隔开。
2、避免在一行代码或表达式的中间插入注释。
3、注释应该与所描述内容进行同样缩排保持整齐,方便阅读。

(六)注释的量:

一般源程序有效注释量必须在20%以上。必须是有助于对程序的理解,准确易懂、清楚无二义性、简洁明了。

(七)注释文件:

1、如开头部分所说,基本说明性文件,.h文件、.inc文件、编译说明文件等。注释的内容类似头文件注释格式。
2、如开头部分所说,重要的源文件,注释内容除写上版权这些以外,注明模块功能,主要实现函数,对外接口函数,修改记录等等。

(八)注释函数:

一般包含 函数功能,输入参数,输出参数,返回值,备注信息,调用列表等。

在这里插入图片描述

(九)模块注释:

在模块前加上一行注释说明模块的功能,在程序块的结束行右方加注释标记,以表明某程序块的结束。

(十)代码主要注释内容:

1、有实际意义的常量、变量、宏:除非其自注释,不然都加上注释。

2、结构体声明(含数组、结构体、类、枚举等):其注释在上方,结构体中的域在其右方注释。

/* 点类型的定义 */
struct SPoint
{   
    int iX;  /* 点的X位置  */
    int iY;  /* 点的Y位置 */
}; 

3、分支语句(条件、循环、switch):每一功能的注释。

4、大程序块结束:加上注释,便于阅读,如if,while,for这些语句的多层嵌套。

5、全局变量:要有比较详细的注释,包含其功能、取值范围、调用者和注释事项等。

 

🚀四、命名规则

标识符:程序员自己规定的具有特定含义的词,比如类名称,属性名称,变量名和函数名等。标识符由字母、数字、下划线“_”组成,关键字不能作为标识符。

标识符命名规则:见名知意,符合规范和标准。

 

⛳(一)基本规则

1、含义精确:标识符应该直观且易读,望文知意。要使用准确的英文字符.。

如:CurrentValue不写成NowValue

2、长度精简:“ min-length && max-information”–最精确精简的词。—长但不要太长

缩写:可用大家基本可用理解的缩写。temp=>tmp; message=>msg;

3、变量名组成:使用"名词"或者“形容词+名词”;

建议除了有具体含义外,还要能表明变量类型:

//匈牙利命名规则
int iwidth; // i表明该变量为int型,width指明是宽度

4、函数名组成:全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。

DrawBox();      // 全局函数
box->Draw();    // 类的成员函数

嵌入式中,如果是相关的模块驱动,前面加上模块名。

void BCT3286_SPI_Init(void);

5、常量:全用大写的字母,用下划线分割单词。

const int MAX    = 100;
const int MAX_LENGTH  = 100;
#define MAX_ARRAY   100
#define SHOW_DTDATA (WM_USER+0x101) //记得带上括号

6、特殊软件库前缀:为了防止某一软件库中的一些标识符和其它软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀。例如三维图形标准OpenGL的所有库函数均以gl开头,所有常量(或宏定义)均以GL开头。

7、不要出现:

(1)仅靠大小写区分的相识标识符。
(2)相同命名的局部和全局变量。
(3)尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。

8、切合操作系统: 命名要切合操作系统与开发工具的风格
 

(1)widows中:

【1】变量和参数用小写字母开头的单词组合而成。(驼峰式命名法)

BOOL flag;
int drawMode;

【2】类名和函数名用大写字母开头的单词组合而成。(帕斯卡命名法)

class LeafNode; // 类名
void SetValue(int value); // 函数名
 

(2)stm32中:

同windows,差别在如果是底层驱动函数要加上模块名。
 

(3)linux应用程序和ARM9嵌入式:

函数和变量这些标识符采用全小写加下划线add_child。(下划线命名法)

【1】变量名必须意义准确。

例如有一个变量用于保存图书的数目,可以命名为number_of_book或者num_of_book。不建议使用i,因为它没有意义。也不建议使用number或book,因为意义不准确。

【2】不建议大小写混用。

如定义一个计数变量,int nCount;这在Windows中是一个很好的变量名,其中nCount的首字母n用来说明这个变量的类型是int。但在Linux下不建议大小写混合使用,一般标识符只由小写字母,数字和下划线构成。

【3】在失去意义的情况下,尽量使用较短的变量名。

例如有一个变量,用于暂时存储一个计数值,把变量命名为tmp_count显然要比this_is_a_temperary_counter好。

【4】不采用匈牙利命名法表示变量的类型。

如int nCount;n用于说明变量的类型,在Linux中不建议这样命名变量。

【5】函数名应该以动词开头。

因为函数是一组具有特定功能的语句块。比如一个函数,它用于取得外部输入的数值,则可以命名为get_input_number。

IIS_pin_init();
set_IIS_for_record();
start_IIS();

【6】尽量避免使用全局变量。


一套良好的命名规则有助于增加代码的可读性和可维护性。我们的目的是为了能使自己和他人更好地阅读我们的代码,对命名的要求不至于太过严苛,但也不可胡来,不限制一定的主观感受(如个人喜好),但最基本的要求是易懂,尽量使用英文单词而少用拼音(不会可以去查)。
 
总结起来,C++常用的命名法主要有以下四种:匈牙利命名法、驼峰命名法、帕斯卡命名法、下划线命名法。

 

⛳(二)匈牙利命名法

现在一般不用,多用在上位机语言

1、 核心思想:

在变量和函数名中加入前缀以增进人们对程序的理解。

2、主要方法:

标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。

标准公式:变量名=属性+类型+对象描述,其中每一对象的名称都要求有明确含义,可以取对象名字全称或名字的一部分。

(1) 变量的命名

所有的变量名都应该以前缀+名字的形式出现。
指针变量记得加’p’。

char* strName;//以’\0’结尾的字符串,存储的数据是名字
int * pTemp;

(2)函数的命名

不需要加前缀,但是每一个单词的第一个字母都需要大写。

void ShowMessage(int ix);//显示信息。

函数采用首字母大写的方式进行拼写。常采用动宾结构,尽量做到简洁明了,禁止使用具有歧义的的词语。如:命函数名ChangeValue,我们就无法得知Value指代的是什么含义,必须以具有明确含义的词语来代替,可改为 ChangeTemperature 表示更改温度值(无需写成ChangeTemperatureValue,因为ChangeTemperature的含义已经够明确了,加上Value反而显得拖沓)。

(3)类型和常量命名:

所有的字母都必须大写

#define MAX_NUM 256  //常量

typedef unsigned char UNCHAR;//类型

(4)枚举类型(enum)中的变量

要求用枚举变量或其缩写做前缀。并且要求用大写。

enum EMDAYS{   
    EMDAYS_MONDAY;   
    EMDAYS_TUESDAY;    
};

(5)对struct、union、变量的命名

类型用大写,并要加上前缀,其内部变量的命名规则与变量命名规则一致。结构体/联合体类型必须采用typedef的方式来定义,结构体类型必须以”S_”(S大写)开头,联合体类型必须以”U_”(U大写)开头。后面全部采用首字母大写的方式拼写,对于原先大写的缩写单词也要采用首字母大写的方式。

结构一般用S开头

struct SPoint  
{   
    int iX; //点的X位置   
    int iY;  //点的Y位置   
};   

联合体一般用U开头

union UPoint  
{   
    long lX;  
    long lY;  
}  

3、常用前缀:

(1)属性前缀

前缀数据类型
g_全局变量
c_常量
m_C++类成员变量
s_静态变量
rg_寄存器变量

(2)类型前缀:

前缀数据类型
cchar 8位字符 ;cGrade
str,sstring 字符型 ;strName
sz以"\0"结束的字符串 ;szAppName
ch字符 char 或 WCHAR 或 TCHAR 如果_UNICODE定义,则为16位字符 ;chName
b,fBOOL 布尔值 ,f 表示“flag”;bEnable
by字节 BYTE (无符号字符)
n,iint 整型(其大小依赖于操作系统);nLength
sishort int 短整型 ;siSequ
nUINT 无符号值(其大小依赖于操作系统);nHeight
wWORD(无符号短整型) 16位无符号值 ;wPos
ffloat 浮点型(有时也指文件) ;fRadius
ddouble 双精度型 ;dArea
lLONG 长整型 ;lOffset
ldlong double 长双精度型 ;ldRate
dwDWORD 双字(32位无符号长整型) ;dwRange
p* 指针 ;pDoc
lpFAR* 远指针 ;lpszName
lpszLPSTR 32位常量字符串指针 ;lpszName
lpszLPCSTR 32位常量字符串指针 ;lpszName
lpszLPCTSTR 如果_UNICODE定义,则为32位常量字符串指针 ;lpszName
hhandle Windows对象句柄 ;hWnd
lpfncallback 指向CALLBACK函数的远指针
if输入文件流 ;ifDataFile
of输出文件流 ;ofStuFile
fn函数
h句柄
x,yint,表示 x 坐标和 y 坐标
cx,cyint,表示 x 或 y 的长度,c 表示“count”(计数)
c(通常用cnt)计数
C类或结构 ; CDocument,CPrintInfo
S结构体 ; SAddress
r实型
u无符号
v无效

类型采用小写字母表示,用于标识变量的数据类型,如是指针类型,则在类型前加上小写的p,如是数组类型,则在类型前面加上小写的a。

(3)描述前缀

前缀数据类型
Max最大
Min最小
Init初始化
T(或Temp)临时变量
Src源对象
Dest目的对象
Value(或者val)
Node节点

示例:

hwnd : h 是类型描述,表示句柄, wnd 是变量对象描述,表示窗口,所以 hwnd 表示窗口句柄;

pfnEatApple : pfn 是类型描述,表示指向函数的指针, EatApple 是变量对象描述,所以它表示指向 EatApple 函数的函数指针变量。

g_cch : g_ 是属性描述,表示全局变量,c 和 ch 分别是计数类型和字符类型,一起表示变量类型,这里忽略了对象描述,所以它表示一个对字符进行计数的全局变量。

 

⛳(三)驼峰命名法

驼峰命名法又被有些人称为小驼峰命名法,是为了和大驼峰命名法区分。

1、基本思想

当变量名或函数名是由一个或多个单词连结在一起,而构成的唯一识别字时,第一个单词以小写字母开始;第二个单词的首字母大写。

2、例如:

printEmployeePaychecks();

函数名使用了骆驼式命名法——函数名中的每一个逻辑断点都有一个大写字母来标记;

 

⛳(四)帕斯卡命名法

每一个单字的首字母都采用大写字母的命名格式,被称为“Pascal命名法”,源自于Pascal语言的命名惯例,也有人称之为“大驼峰式命名法”(Upper Camel Case)。

1、基本思想

单字之间不以空格断开或连接号(-)、底线(_)连结,第一个单字首字母采用大写字母;后续单字的首字母亦用大写字母。与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写,

2、例如:

public void DisplayInfo();
string UserName;

相比小驼峰法,大驼峰法把第一个单词的首字母也大写了。常用于函数名,类名,属性。

 

⛳(五)下划线命名法

1、基本思想:

又被称为蛇形命名法,如 my_variable。常见于Linux内核,C++标准库。改命名法可读性稍好,但是会增加命名的长度和输入的难度。

2、例如:

print_employee_paychecks();

骆驼式命名法近年来越来越流行了,在许多新的函数库和Microsoft Windows这样的环境中,它使用得当相多。另一方面,下划线法是c出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中,它的使用非常普遍。

 

⛳(六)文件名

1、基本思想:

文件标识符分为两部分,即文件名前缀和后缀。文件名前缀的最前面要使用范围限定符——模块名(文件名)缩写。采用小写字母命名文件,避免使用一些比较通俗的文件名,如:public.c 等。

头文件一般用来写模块里的一些函数的声明,实现写在源文件中,因此源文件前缀名最好与对应的头文件名字相同,如:snake.h对应的源文件 可命名为snake.c。

文件名要全部小写,用“_”分割;保持整个项目风格统一;

c文件以.c结尾,头文件以.h结尾;C++文件以.cpp结尾,头文件以.hpp结尾;cpp和hpp成对出现;

2、示例:

tcp_server.hpp
tcp_server.cpp

 

⛳(七)个人习惯命名总结

(1)类名:大驼峰风格

(2)类的成员函数、普通函数:小驼峰风格

(3)变量、对象名:小驼峰

(4)符号常量:全部大写,用下划线分割单词。 #define MAX_AGE 30 (一般用于宏)

(5)小驼峰的都可以用下划线方式,不过我喜欢用小驼峰

(6)请忘记“匈牙利命名法”(属性+类型+对象描述),这种方法已经很少使用

(7)在Qt类中,普通C++程序类中,静态变量前也可以加s_。如:static int s_rate;类的数据成员前面加m_。 如:private: int m_salary;

如果想用两个或更多的单词组成一个名称,通常的做法是用下划线字符将单词分开,如my_onions;或者从第二个单词开始将每个单词的第一个字母大写,如myEyeTooth(驼峰命名法)。(C程序员倾向于按C语言的方式使用下划线,而Pascal程序员喜欢采用大写方式。)这两种形式都很容易将单词区分开,如carDrip和cardRip或boat_sport和boats_port。

没有规定就遵循通常习惯。比如通常i,j,k表示循环控制变量,m,n,k通常表示整数或者数据个数。x,y,z通常表示数学中的变量或者坐标。

 

🚀五、宏、全局变量和其他注意

(一)宏的使用+定义规范:

1、由来:不易理解的数字和常量则用有意义的枚举或者宏来替代:

#define BUFF_SIZE     1024
input_data = (char *)malloc(BUFF_SIZE);

2、宏定义规范

(1)括号:宏定义表达,需要完整的括号。

#define GET_AREA(a,b) ((a) * (b))

(2)大括号:宏中有多条语句,应将语句放在一对大括号中。

#define INTI_RECT_VALUE( a, b ) {
	a = 0;
    b = 0;
}

(二)全局变量:

1、避免使用: 尽量避免使用,它占用程序空间,同时增大了模块间的耦合性,不利于软件维护。

2、规范:应明确其含义、作用、取值范围。明确全局变量与操作此变量的函数的关系,如创建、访问、修改。

(三)其他原则

1、专一:一行代码只做一件事情,如只定义一个变量,或只写一条语句。—易阅读和注释。

2、就近原则:尽可能在定义变量的同时初始化该变量。

3、数据大小端统一:通信协议中数据的大小端要和整个团队形成统一。
 

🚀六、函数和类

(一)函数

1、函数名:应能准确描述函数功能,一般以动词加宾语的形式;print_record

2、参数个数:不宜过多,1-3个为好;

3、返回值:清楚、明了,让调用者不易忽视错误情况。每种错误的返回值要清晰、明确,防止调用者误用;

linux中函数的返回值:正常的时候返回0,错误的时候返回-1或者小于零的错误码。

WINDOWS和stm32函数返回值:如果GetCommState()函数调用成功,则返回值大于零。若函数调用失败,则返回值为零,如果想得到进一步的错误信息,可以调用GetLastError()函数来获取。

4、输入参数:检查其有效性,如指针型参数判断是否为空,数组成员是否越界等等;

5、规模:限制在200行以内(不含空行和注释行);

6、功能专一:一个函数完成一个特定功能;

7、功能可预测:输入数据相同,能得到可预期的输出;

8、代码重用:多段代码重复做一件事,考虑将重复功能实现成一个函数;

9、独立性:减少与其他函数的联系,提高可读性、维护性和效率。避免函数本身和函数间的递归调用,递归影响可读性和系统资源如栈空间。

(二)类

类可以将数据和函数封装在一起,其中函数表示了类的行为(或称服务)。类提供关键字public、protected和private,分别用于声明哪些数据和函数是公有的、受保护的或者是私有的。

主张提倡的书写方式:将public类型的函数写在前面,而将private类型的数据写在后面,这种版式的程序员主张类的设计“以行为为中心”,重点关注的是类应该提供什么样的接口(或服务)。即首先考虑类应该提供什么样的函数。“这样做不仅让自己在设计类时思路清晰,而且方便别人阅读。因为用户最关心的是接口,谁愿意先看到一堆私有数据成员!”

class A
{
public:
    void Func1(void);
    void Func2(void);
private:
    int i, j;
    float x, y;
}

 

🚀七、编程规范杂烩

1、变量和零值比较

分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)。

解答:

   BOOL型变量:if(var)  if(!var)
       
   int型变量: if(var==0)

   float型变量:

        const float EPSINON = 0.000001;

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

   指针变量:  if(var==NULL) if(var!=NULL)

剖析:

考查对0值判断的“内功”,BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思,属于不良风格。一般的,如果想让if判断一个变量的“真”、“假”,应直接使用if(var)、if(!var),表明其为“逻辑”判断。

如果用if判断一个数值型变量(short、int、long等),应该用if(var==0),表明是与0进行“数值”上的比较;

而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯和编程风格。

浮点型变量并不精确,所以不可将float变量用“==“或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。如果写成if (x == 0.0),则判为错。


参考文章:

作者:张痕: C/C++编程规范整理
作者:千瞱: C/ C++命名规则总结
作者:Leon_Chan0: C++编程(一):匈牙利命名法

若相关博主看见有侵权行为,请联系我删除,感谢大佬优秀的文章对我学习上的帮助。


文章停留在日落,但人生还要继续书写。

在这里插入图片描述

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈七.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值