C语言编写规范与速成教程.docx
《C语言编写规范与速成教程.docx》由会员分享,可在线阅读,更多相关《C语言编写规范与速成教程.docx(41页珍藏版)》请在冰豆网上搜索。
![C语言编写规范与速成教程.docx](https://file1.bdocx.com/fileroot1/2023-5/23/d41e70f4-d4cf-4006-aa4b-0ddf395e8abd/d41e70f4-d4cf-4006-aa4b-0ddf395e8abd1.gif)
C语言编写规范与速成教程
C语言编写规范与速成教程
一.C语言编写规范
目录
1.说明5
2.程序约定5
2.2.1应用程序的命名5
2.2.2子模块的命名6
2.2.3变量的命名6
2.2.4常量的命名7
2.2.5函数/过程的命名7
2.2.6接口命名7
2.2.7类的命名8
2.2.8方法的命名8
2.2.9数据库的命名8
2.3.1输入参数的约定9
2.3.2输出参数的约定9
2.3.3返回值的约定9
2.4.1源程序头的注释和规范9
2.4.5区的注释10
2.4.6代码中的注释11
3.接口/函数过程调用的约定12
3.1头文件(.h文件)12
3.2函数13
3.2.1变量定义13
3.2.2参数合法性检查13
3.2.3执行处理13
3.2.4返回值14
4.错误和异常处理规范14
4.1出错类型定义约定14
4.2异常的捕获15
4.3异常和错误的处理15
1.说明
为了保证在软件开发过程中,全体成员的代码风格一致,便于维护,提高软件产品的质量和保持开发产品的持续性,特制定本编码规范。
本规范详细规定了源码书写、变量命名、函数/过程的书写、错误和异常处理等方面。
2.程序约定
2.1排版规则
1) 程序应采用缩进风格编写,每层缩进使用一个制表位(TAB),类定义、方法都应顶格书写;
2) 左花括号要另起一行,不能跟在上一行的行末;
3) 一个变量定义占一行,一个语句占一行;
4) 对独立的程序块之间,变量说明之后必须加空行;
5) 对于较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;
6) 循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分;
7) 在结构成员赋值等情况,等号对齐,最少留一个空格;
8) 若函数或过程中的参数较长,则要进行适当的划分;
9) 形参的排序风格
◆ 最常使用的参数放在第一位
◆ 输入参数列表应放在输出函数列表的左边
◆ 将通用的参数放在特殊的参数的左边
2.2命名约定
2.2.1应用程序的命名
“公司所写”+模块名称+[版本]
2.2.2子模块的命名
每个子模块的名字应该由描述模块功能的1~3个单词组成。
每个单词的首字母应大写。
在这些单词中可以使用一些较通用的缩写。
2.2.3变量的命名
变量的命名的基本原则使使得变量的含义能够从名字中直接理解。
可以用多个英文单词拼写而成,每个英文单词的首写字母要大写,其中英文单词有缩写的可用缩写,变量的前缀表示该变量的类型;对于作用域跨于10行以上的变量名称不能少于4个字符,除循环变量,累加变量外不得使用i、j、k等名称的变量名。
变量分为全局变量和局部变量,对于全局变量以加前缀“g_”来区分。
变量类型
前缀
说明
变量类型
前缀
说明
int
N
整形值
BYTE
By
8位无符号整形值
long
L
长整形值
COLORREF
Cr
32位的颜色值
unsignedint
Ui
无符号整形值
DWORD
Dw
32位无符号整形值
unsignedlong
Ul
无符号长整形值
LONG
L
32位整形值
char
C
字符
LPARAM
Lparam
32位值,作为参数给窗口过程或回调函数
char*
P
字符数组
LPCSTR
Psc
32位指针,常量字符串
char*
Sz
以\0结尾的字符串
LPSTR
Ps
32位指针,字符串
Float
F
单精度浮点值
LPCTSTR
Psts
32位指针,常量字符串,Unicode和DBCS
Double
D
双精度浮点值
LPTSTR
Pts
32位指针,字符串,Unicode和DBCS
Bool
B
布尔型
LPVOID
P
32位指针,没有指定
LRESULT
Lr
32位的返回值
UNIT
U
无符号整形值
WNDPROC
Pwnd
32位窗口过程指针
WORD
W
16位无符号整形值
POSITION
Pos
MFC集合类中,显示元素在集合中的位置
WPARAM
wparam
32位值,作为参数给窗口过程或回调函数
LPCRECT
Pc
32位指针,指向常量RECT结构
指针
P
一般指针类变量通用
另外,要注意的是:
全局变量在程序中不要定义太多,能用局部变量变量的就用局部变量。
如果要使用相关的变量,建议采用类的方式或者结构的方式存放,以减少具体变量的个数。
2.2.4常量的命名
常量所有的字母均为大写。
并且单词之间使用下划线“_”隔开。
2.2.5函数/过程的命名
函数/过程名称应该尽量使用表达式函数功能的英文名称,函数名称中应该禁止使用如同function1,function2等含义不清的名称。
单词间应该使用大小写分割。
全局函数/过程以“g_”前缀开始。
2.2.6接口命名
接口名称要以大写字母开头。
如果接口包含多个单词,每个单词的首字母大写,其他字母小写,如果,这些单词是缩略语(例如XML),也要首写字母大写,其他字母小写(Xml)
2.2.7类的命名
1) 类名称要以大写字母开头;
2) 类名称如果包含多个单词,每个单词的首字母要大写,其他字母小写,如果这些单词是缩略语(例如XML),也要首写字母大写,其他字母小写(Xml);
3) 类名称应该是一个名词或名词短语;
4) 类成员变量的命名规则与上述规则相同,但是要以“m_”开始,表示其为成员变量(Member);
5) 类名称不能出现下划线。
2.2.8方法的命名
1) 方法名称以小写字母开头;
2) 方法名称如果包含多个单词,除了第一个单词外,每个单词的首字母大写,其他字母小写。
如果这些单词是缩略语(例如XML),也要首写字母大写,其他字母小写(Xml);
3) 方法名称应该是一个动词或动名词短语,意思是“完成什么功能”,“执行什么操作”;
2.2.9数据库的命名
1) 表:
采用模块名称+前缀+“_”+表名的命名规则。
◆ 表名以能够理解该表的内容为原则,可由中文表示,也可以由代表此表含义的英文字母组成,首字母大写;
◆ 前缀代表此表类别。
2) 视图:
采用模块名+“_”+视图名+“视图”的命名规则,通常由8个以内汉字组成。
3) 存储过程:
采用“Proc”+模块名+“_”+存储过程名的命名规则
4) 触发器:
采用模块名+“_”+触发类型+“_”+表名的命名规则,如果有多个触发类型,则可以叠加在一起。
5) 字段:
字段的命名以能够理解该字段的含义为原则,通常由多个英文单词加前缀拼写而成,而组成字段名称的首字母应大写。
单词有缩写的可用缩写。
字段的前缀表示该字段的数据类型,其取值详见“数据类型”描述。
原则上,字段的命名长度不超过18字节;描述字段的中文名称,用数据库创建工具设计数据库时,需要输入。
2.3参数的约定
2.3.1输入参数的约定
有些函数有输入参数,这些参数指由函数外部(调用者)输入,并在函数内部使用。
在函数业务流程说明后跟输入参数说明区,用“输入参数”或“InputParameters”标记。
在参数名列表中的每个参数后增加该参数的注释。
2.3.2输出参数的约定
有些函数有输出参数,这些参数指由函数外部(调用者)定义,在函数内部使用并返回给调用者的参数。
在输入参数说明区后跟输出参数说明区,用“输出参数”或“OutputParameters”标记。
在参数名列表中的每个参数后增加该参数的注释。
另外输出参数一般以指针或应用输出。
2.3.3返回值的约定
每个函数均有返回值,除非操作非常简单,对于有不同状态的返回值,建议用long型的返回值,0为成功。
对于出错类返回值,在同一层次的模块,用同一代码表示。
在输出参数说明区后跟返回值说明区,用“返回值”或“ReturnValues”标记,返回值说明,要说明各种不同类型返回值以及它们的含义。
2.4注释约定
在软件中对每个文件头,自定义函数和变量,重要的处理过程都要有必要的注释。
2.4.1源程序头的注释和规范
每个文件头插入注释,标明文件的用途和作者,注释如下:
(注释尽量用中文)
//程序名称
//版权说明
//版本号:
//功能:
//开发人:
//开发时间:
//修改者:
//修改时间
//修改简要说明
//其他
2.4.2函数的注释
每个函数前面注明函数的功能和输入、输出。
注释为:
//名称
//功能:
(说明函数的功能)
//输入参数:
(说明每个输入参数的用途和取值约定)
//输出参数:
(说明每个输出参数的用途和取值约定)
//返回:
(说明返回值,返回值的含义和约定)
2.4.3变量注释
直接在变量后面注明变量的用途和取值约定,如:
intstatus; //记录处理状态,0:
成功,1:
错误
2.4.4类型定义注释
指类和记录等等定义的注释,在注释中标明定义的用途。
2.4.5区的注释
1) 同一类的成员方法要求排列在一起,共同协作而实现同一个功能的函数和过程要求排列在一起。
代码通常使用几个函数和过程来实现某一项功能,这时候需要使用区注释将这些具有共同目的的函数和过程标明出来。
2) 使用整行的“*”作为隔离行,让程序清晰可读。
3) 一般删除的代码不建议直接删除,最好用“//”注释起来。
2.4.6代码中的注释
在代码中要求注释的地方有:
1) 代码中的关键部分;
2) 在使用特殊算法或者逻辑性较强的代码;
3) 在修改或删除代码部分,需要加注释;修改/删除人,目的
2.5变量的作用范围
尽量做到缩小变量的作用范围,对于变量是指针的,应遵循以下约定:
1) 在局部分配的空间在局部释放。
2) 函数体内不能分配空间并将空间指针作为函数参数返回。
3) 动态全局空间在程序结束时一定要释放。
4) 所有动态分配的空间在对应层次的模块释放,并且用完马上释放。
不重复释放相同的指针。
2.6函数/过程的定义
在函数的定义处应当增加本函数的功能描述的注释。
1) 用一句话描述清楚功能。
2) 可用英文或中文。
3) 功能注释格式要求所有代码一致。
2.7函数业务流程的定义
在函数功能描述后,要增加函数的主要业务流程注释。
1) 可以用多行描述,以解释清楚业务流程为主。
2) 可用英文或中文。
3) 业务流程注释格式要求所有代码一致。
4) 业务流程注释可以尽量详细,注释的长度可以与代码长度差不多,但是不要太长。
比如处理N阶乘的函数业务流程定义如下:
/*Process:
Nfactorialusecallbackfunctiontoimplement. */
/*IfN==othenreturn1elsereturnN-1factorial. */
或
/*过程:
N阶乘利用回调函数实现。
如果N等于零,则返回1。
*/
/*否则返回N-1的阶乘。
*/
注意:
函数业务流程的说明并不在乎有多长,但是在乎能否说明过程,有些像N阶乘的函数流程比较简单,但是有些比较复杂。
当比较复杂时,可以用标号来说明。
3.接口/函数过程调用的约定
几乎每一个项目中,都存在开发接口API给其他应用调用,本规范适用于标准C开发接口API。
3.1头文件(.h文件)
提供给使用API的应用的标准C头文件。
头文件必须包含三部分。
1) 防止头文件重复引用的编译条件
即我们在创建文件时必须增加以下的条件编译:
#ifndef#define#endif。
比如要防止abcqueue.h头文件被重复引用,必须在abcqueue.h增加以上的条件编译:
#ifndef_ABCQUQUE_H
#define_SMBUS_H
……
#endif
2) 函数定义
函数的定义是为了方便应用知道LIB、DLL里引出了怎样的API,应该如何使用。
如下面的例子。
3) 错误代码定义
错误代码是接口API里因为内部某种错误返回的代码,它告诉应用出现了什么错误,以便开发者进行调试和排错。
3.2函数
提供给应用调用的执行体。
实现函数时,必须根据以下规范开发
3.2.1变量定义
在函数代码中,变量的定义必须放在第一部分,同时给指针类型的变量赋空(NULL)。
3.2.2参数合法性检查
在使用应用传递的输入输出参数之前,必须对参数进行合法性检查,保证代码执行使用参数的安全性。
比如,应用的一个输出参数地址为NULL,如果处理之前不检查参数的合法性,那么将导致一个内存错误;如果检查合法性,就不会造成代码执行时出现问题。
3.2.3执行处理
在处理代码开发中,必须注意以下的一系列的问题:
1) 对应用传递的输入输出参数,禁止使用strcpy,strlen,strcat,strcmp等相应的函数操作输入输出参数,尽量使用strncpy,memcpy等含有处理长度参数的函数惊醒处理。
2) 必须先分配系统资源,才能分配函数内部需要的资源;相反,必须首先释放函数内部分配的资源,再释放系统资源。
3.2.4返回值
对外接口API必须返回返回值给应用
4.错误和异常处理规范
4.1出错类型定义约定
1) 在整个系统软件产品的出错定义要一致;
2) 统一模块层次的出错类型统一;
3) 出错类型分为错误、警告、提示等三类信息,分别用E、W、I开头
4) 错误代码统一用宏描述,并且在一个头文件中;
5) 出错代码的宏定义还要加注对这个代码的说明;
6) 出错代码有相应的文档指明代码的定义规则。
例子:
有ErrorDef.h中有如下定义:
//***************************************************************
//ErrorCodeMacroDefine
//***************************************************************
//ErrorCode
#defineE_OK 0x0 //没有错误
#defineE_NO_ENOUGH_MEMORY 0x1001 //内存不足
#defineE_INVALID_HANDLE 0x1002 //无效的句柄
//WarningCode
#defineW_CUT_RECV_DATA 0x2001 //裁减接收数据
#defineW_FIND_OLD_MESSAGE 0x2002 //发现老的消息
//InformationCode
#defineI_SEND_SUCCED 0x9001 //发送成功
注意:
出错类型的定义一定要统一,并且一定要注意编码问题。
4.2异常的捕获
在程序中会出现各种异常,如除0错误,内存错误都要处理。
要有异常可能的都要捕获。
4.3异常和错误的处理
每个函数独立处理内部的异常,对影响结果的异常通过返回值返回。
对于在函数内部不能处理的异常,捕获后以另外的形式向调用者抛出。
但是要在接口文档中详细写明。
注意:
处理异常一般有两种方法,一是通过将异常转化为另一个异常抛出,二是通过函数返回值返回。
在本规范中,我们倾向于用第二种方法。
二.C语言速成教程
相信很多爱好电子的朋友,对单片机这个词应该都不会陌生了吧。
不过有些朋友可能只听说他叫单片机,他的全称是什么也许并不太清楚,
更不用说他的英文全称和简称了。
单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。
简称为:
单片微型计算机或单片机
(SingleChipComputer)。
单片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。
不过这一切都没
什么关系,因为我(当然也包括任何人)都是从不知道转变成知道的,再转变成精通的。
现在我只想把我学习单片机的经历,详细地讲叙给大
家听听,可能有些大虾会笑话我,想:
那么简单的东西还在这里卖弄。
但是你错了,我只是把我个人学习的经历讲述一遍而已,仅仅对那些想
学习单片机,但又找不到好方法或者途径的朋友,提供一个帮助,使他们在学习过程中,尽量少走些弯路而已!
首先,你必须有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什
么东西了。
还是先说说我吧,我从大二的第一个学期期末的时候才开始接触单片机,但在这之前,正如上面所说的:
我知道有种芯片叫单片机,
但是具体长成什么样子,却一点也不知道!
看到这里很多朋友一定会忍不住发笑。
嘿嘿,你可千万别笑,有些大四毕业的人也同样不知道单片
机长成什么样子呢!
而我对单片机的痴迷更是常人所不能想象的地步,大二的期末考试,我全放弃了复习,每当室友拿着书在埋头复习的时候,
我却捧着自己从图书馆借的单片机书在那看,虽然有很多不懂,但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出,
或许这也是在一些三流学校的好处吧,考试挂科后,明年开学交上几十元一门的补考费,应该大部分都能过了。
于是,我横下一条心,坚持看
我的单片机书和资料。
当你明白了单片机是这么一回事的时候,显而易见的问题出来了:
我要选择那种语言为单片机编写程序呢?
这个问题,困扰了我好久。
具
体选择C51还是A51呢?
汇编在我们大二之前并没有开过课,虽然看着人家的讲解,很容易明白单片机的每一时刻的具体工作情况,但是一合上
书或者资料,自己却什么也不知道了,根本不用说自己写程序了。
于是,我最终还是决定学C51,毕竟C51和我们课上讲的C语言,有些类似,
编程的思想可以说是相通的。
而且C51还有更大的优点就是编写大程序时的优越性更不言而喻,当然在那时,我并没有想的那么深远,C51的特
点,还是在后来的实践过程中,渐渐体会到的!
朋友如果你选择了C51,那么请继续往下看,如果你选择了A51,那么你可以不要看了!
因为下面讲
的全是C方面的,完全在浪费你的时间!
呵呵^_^
第二,既然你想学好单片机,你必须得舍得花钱,如果不买些芯片回来自己动手焊焊拆拆的(但是在后期会介绍给大家一个很好用的硬件
仿真软件,并不需要你用实验板和仿真器了,直接在你的PC上完成,但是软件毕竟是软件,从某个特定的意义上来说是并不能代替硬件的),即使
你每天捧着本书,把那本书翻烂,也永远学不会单片机的!
刚接触单片机的朋友,看了资料,一定会对以下几个词见的比较多,但是具体的概
念还是比较模糊,现作如下说明:
(1)编程器编程器是用来烧单片机芯片的,是把HEX或者BIN文件烧到单片机ROM里的,供单片机运行的。
(2)实验板实验板是专为初学者根据某些要求而特做的板,一般上面就有一个单片机的最小系统,使用者只需写好程序,烧好芯片,放
到上面加以验证的这么一个工具。
有了实验板,对与初学者来说,省去了焊个最小系统的麻烦。
但是对于电子开发人员来说,作用并不是很大
(3)仿真器仿真器是直接把HEX或者BIN文件暂时放在一个芯片里,再通过这个芯片的引脚连接到实验板或者系统上工作。
这样以来,可
以省去了来回插拔芯片带来的不必要麻烦。
我一开始也不知道上面3个的概念和作用,嘿嘿,原本想买个实验板(不想焊板,因为不可能为了点亮几个流水灯,而去焊个单片机的最小系统)
的,可是结果,确和我想的正好相反,人家出售的是编程器。
等货物寄到后,才知道自己搞错了!
汗。
。
。
嘿嘿。
现在想想实在是又气又笑。
我花
了160大样买了个编程器(很不幸的是,这个编程器更本用不了,一烧芯片,芯片就烧坏了)把我给气的,这个编程器,现在还躺在我的抽屉里
呢不过,现在想想,唯一让我觉得欣慰的是,那个老板每次能解答我的问题,连那种超级幼稚的问题,他也能不嫌麻烦地尽量帮我解答!
这点让
我很感动!
第三,想学单片机的必需品--PC。
因为写程序,编译或者是仿真都是通过PC完成的。
如果没有PC,什么也做不了!
!
!
有了PC最好还要可
以上网,因为如果你没有可以和你交流单片机的人,遇到自己解决不了的问题,一直都想不通,那么估计你学习单片机的热情就会随着时间的
推移而慢慢耗尽。
如果你能上网通过论坛或者QQ群,问题就很快得到解决。
这样的学习效率一定很高!
真正的高手是从论坛中泡出来的!
有了上述3个条件后,你就可以开始学你的单片机了。
但是,真的做起来并没有我所说的那么简单。
你一定会遇到很多很多的问题。
比如
为了让单片机实现某个功能,你可能不知道怎么去写某个程序。
或是你看懂了资料上某个相似的程序,你自己却写不出来。
遇到类似的情况,
记住:
千万不要急噪,就行!
(二)
说了这么多了,相信你也看了很多资料了,手头应该也有必备的工具了吧!
(不要忘了上面讲过几个条件的哦)。
那个单片机究竟有什么
功能和作用呢?
先不要着急!
接下来让我们点亮一个LED(搞电子的应该知道LED是什么吧^_^)
我们在单片机最小系统上接个LED,看我们能否点亮它!
对了,上面也有好几次提到过单片机最小系统了,所谓单片机最小系统就是在单片机
上接上最少的外围电路元件让单片机工作。
一般只须连接晶体、VCC、GND、RST即可,一般情况下,AT89C51的31脚须接高电平。
#include //头文件定义。
或用#include其具体的区别在于:
后者定义了更多的地址空间。
//在Keil安装文件夹中,找到相应的文件,比较一下便知!
sbitP1_0=P1^0; //定义管脚
voidmain(void)
{
while
(1)
{