《计算机程序设计基础》课程学习指南(C语言)C语言初学者编程规范-1/2

C语言初学者编程规范对于程序员来说,能工作的代码并不等于"好"的代码。“好"代码的指标很多,包括易读、易维护易移植和可靠等。其中,可靠性对嵌入式系统非常重要,尤其是在那些对安全性要求很高的系统中,如飞行器、汽车和工业控制中。这些系统的特点是:只要工作稍有偏差,就有可能造成重大损失或者人员伤亡。一个不容易出错的系统,除了要有很好的硬件设计(如电磁兼容性),还要有很健壮或者说安全"的程序。然而,很少有程序员知道什么样的程序是安全的程序。很多程序只是表面上可以干活,还存在着大量的隐患。当然,这其中也有C语言自身的原因。因为C语言灵活的编程方式和语法规则,对于个新手来说很可能会成为机关重重的陷阱。同时,C语言的定义还并不完全,即使是国际通用的C语言标准,也还存在着很多未完全定义的地方。要求所有程序员都成为C语言专家,避开所有可能带来危险的编程方式,是不现实的。最好的方法是有一个针对安全性的C语言编程规范,告诉程序员该如何做。本规范在制定过程中,主要参考了业界比较推崇的《华为软件编程规范和范例》和《MISRA2004规则》,适合于非计算机专业的C语言初学者使用,目的在于在教学中培养良好的编程规范和意识素质,促进所设计程序安全、健壮、可靠、可读与可维护(程序简单、清晰)。考虑到面向的是初学者,为便于教学和课程考核操作,本规范中的要求比较基本。事实上,很多公司都有自己已规定的代码风格,包括命名规则、缩进规则等,参加工作后,应再进一步学习和应用公司的规范建议在学习本规范的同时,花点时间阅读本规范的参考文献原文,深刻理解编程规范与程序安全、健壮、可靠、可读、可维护间的关系和作用,在学习和工作中养成良好的编程风格。1排版1.1严格采用阶梯层次组织程序代码函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。程序块的分界符(如C/C++语言的大括号和})应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。各层次缩进的风格采用TAB缩进(TAB宽度原则上使用系统默认值,TC使用8空格宽度,VC使用4空格宽度)。示例:if (x is true)1wedo y1else1if (a >b)(1.else17和:if (x == y)1
C语言初学者编程规范 对于程序员来说,能工作的代码并不等于"好"的代码。"好"代码的指标很多,包括易读、易维护、 易移植和可靠等。其中,可靠性对嵌入式系统非常重要,尤其是在那些对安全性要求很高的系统 中,如飞行器、汽车和工业控制中。这些系统的特点是:只要工作稍有偏差,就有可能造成重大损 失或者人员伤亡。一个不容易出错的系统,除了要有很好的硬件设计(如电磁兼容性),还要有很健壮 或者说"安全"的程序。 然而,很少有程序员知道什么样的程序是安全的程序。很多程序只是表面上可以干活,还存在着 大量的隐患。当然,这其中也有C语言自身的原因。因为C语言灵活的编程方式和语法规则,对于一 个新手来说很可能会成为机关重重的陷阱。同时,C语言的定义还并不完全,即使是国际通用的C语 言标准,也还存在着很多未完全定义的地方。要求所有程序员都成为C语言专家,避开所有可能带来 危险的编程方式,是不现实的。最好的方法是有一个针对安全性的C语言编程规范,告诉程序员该如 何做。 本规范在制定过程中,主要参考了业界比较推崇的《华为软件编程规范和范例》和《MISRA 2004 规则》,适合于非计算机专业的C语言初学者使用,目的在于在教学中培养良好的编程规范和意识、 素质,促进所设计程序安全、健壮、可靠、可读与可维护(程序简单、清晰)。考虑到面向的是初学 者,为便于教学和课程考核操作,本规范中的要求比较基本。事实上,很多公司都有自己规定的代 码风格,包括命名规则、缩进规则等,参加工作后,应再进一步学习和应用公司的规范。 建议在学习本规范的同时,花点时间阅读本规范的参考文献原文,深刻理解编程规范与程序安 全、健壮、可靠、可读、可维护间的关系和作用,在学习和工作中养成良好的编程风格。 1 排版 1.1 严格采用阶梯层次组织程序代码 函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case 语句下的情 况处理语句也要遵从语句缩进要求。 程序块的分界符(如C/C++ 语言的大括号‘{’ 和‘}’)应各独占一行并且位于同一列,同时与引用它们的语 句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if 、for 、do 、while 、 switch 、case 语句中的程序都要采用如上的缩进方式。 各层次缩进的风格采用TAB缩进(TAB宽度原则上使用系统默认值,TC使用8空格宽度,VC使用4空格 宽度)。示例: if (x is true) { we do y } else { if (a > b) { . } else { . } } 和: if (x == y) {

1else if (x >y)1else(1注意,右括号所在的行不应当有其它东西,除非跟随着一个条件判断。也就是do-while语句中的"while",象这样do(body of do-loop1while (condition);说明:代码离不开缩进,缩进背后的思想是:清楚地定义一个控制块从哪里开始,到哪里结束。尤其是在你连续不断的町了20个小时的屏幕后,如果你有大尺寸的缩进。你将更容易发现缩进的好处。关于缩进主要有两个争论,一个是该用空格(Space)还是用制表符(Tab),另外一个是该用4格缩进还是8格缩进甚至都不是。建议总是使用Tab缩进,因为几乎所有的代码(不仅仅是C代码)都在使用Tab缩进。现在,有些人说8个字符大小的缩进导致代码太偏右了,并且在一个80字符宽的终端屏幕上看着很不舒服。对这个问题的回答是:如果你有超过3个级别的缩进,你就有点犯糊涂了,应当修改你的程序。简而言之,8个字符的缩进使程序更易读,而且当你把功能隐藏的太深时,多层次的缩进还会对此很直观的给出警告。要留心这种警告信息。例外:对于由开发工具自动生成的代码可以有不一致。1.2及时折行较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进(至少1个TAB位置),使排版整齐,语句可读。示例:report_or_not_flag=(taskno<MAX_ACT_TASK_NUMBER)&&(n7statstat_item_valid (stat_item))&&(acttask_table[taskno].result_data !=0));循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。示例:if (taskno<max_act_task number)&& (n7stat_stat item_valid (stat item)))(...//programcode7for (i= 0,j= O; (i< BufferKeyword[word index).word length)&&(j<NewKeyword.word_length);i++,j++){...l programcodefor (i= 0,j= 0(i<first_word_length)&&(j<second_word_length);i++, j++){../l programcode1
} else if (x > y) { . } else { . } 注意,右括号所在的行不应当有其它东西,除非跟随着一个条件判断。也就是do-while语句中 的"while",象这样: do { body of do-loop } while (condition); 说明:代码离不开缩进,缩进背后的思想是:清楚地定义一个控制块从哪里开始,到哪里结束。尤 其是在你连续不断的盯了20个小时的屏幕后,如果你有大尺寸的缩进。你将更容易发现缩进的好 处。 关于缩进主要有两个争论,一个是该用空格(Space)还是用制表符(Tab),另外一个是该用4格缩进还 是8格缩进甚至都不是。建议总是使用Tab缩进,因为几乎所有的代码(不仅仅是C代码)都在使用Tab 缩进。 现在,有些人说8个字符大小的缩进导致代码太偏右了,并且在一个80字符宽的终端屏幕上看着很不 舒服。对这个问题的回答是:如果你有超过3个级别的缩进,你就有点犯糊涂了,应当修改你的程 序。简而言之,8个字符的缩进使程序更易读,而且当你把功能隐藏的太深时,多层次的缩进还会对 此很直观的给出警告。要留心这种警告信息。 例外:对于由开发工具自动生成的代码可以有不一致。 1.2 及时折行 较长的语句(>80 字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行 之首,划分出的新行要进行适当的缩进(至少1个TAB位置),使排版整齐,语句可读。示例: report_or_not_flag = ((taskno < MAX_ACT_TASK_NUMBER) && (n7stat_stat_item_valid (stat_item)) && (act_task_table[taskno].result_data != 0)); 循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作 符处划分新行,操作符放在新行之首。示例: if ((taskno < max_act_task_number) && (n7stat_stat_item_valid (stat_item))) { . // program code } for (i = 0, j = 0; (i < BufferKeyword[word_index].word_length) && (j < NewKeyword.word_length); i++, j++) { . // program code } for (i = 0, j = 0; (i < first_word_length) && (j < second_word_length); i++, j++) { . // program code }

若函数或过程中的参数较长,则要进行适当的划分。示例n7stat_str_compare((BYTE*)&stat_object,(BYTE*)& (act_task_table[taskno].stat_object),sizeof(STAT_OBJECT));n7stat_flash_act_duration(stat_item,frame_id*STAT_TASK_CHECK_NUMBER+index,stat_object);1.3一行只写一条语句不允许把多个短语句写在一行中,即一行只写一条语句。示例,如下例子不符合规范rect.length = O; rect.width= O;应如下书写rect.length = O;rect.width=O;1.4if、for、do、while等语句格式规定if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加花括号。1.5空行(1)变量说明之后必须加空行。(2)相对独立的程序块之间应加空行。1.6空格在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。采用这种松散方式编写代码的目的是使代码更加清晰。由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在CIC++语言中括号已经是最清晰的标志了在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。(1)逗号、分号只在后面加空格。int a, b, C;(2)比较操作符,赋值操作符"="、"+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符=MAX_TIME_VALUE)La=b+c;a *= 2;a=b^2;(3)"!"、"~"、"++"、"-"、"&"(地址运算符)等单目操作符前后不加空格。*p=a';I内容操作"*"与内容之间flag=!isEmpty:l/非操作"!"与内容之间p=&mem;Ⅱ/地址操作"&"与内容之间ⅡI"++""-"与内容之间i++;(4)"->"、"."前后不加空格。p->id=pid;I/"->"指针前后不加空格(5)if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。if (a>=b &&c>d)
若函数或过程中的参数较长,则要进行适当的划分。示例: n7stat_str_compare((BYTE *) & stat_object, (BYTE *) & (act_task_table[taskno].stat_object), sizeof (_STAT_OBJECT)); n7stat_flash_act_duration( stat_item, frame_id *STAT_TASK_CHECK_NUMBER + index, stat_object ); 1.3 一行只写一条语句 不允许把多个短语句写在一行中,即一行只写一条语句。示例,如下例子不符合规范: rect.length = 0; rect.width = 0; 应如下书写 rect.length = 0; rect.width = 0; 1.4 if、for、do、while等语句格式规定 if 、for 、do 、while 、case 、switch 、default 等语句自占一行,且if 、for 、do 、while 等语句的 执行语句部分无论多少都要加花括号{}。 1.5 空行 (1)变量说明之后必须加空行。 (2)相对独立的程序块之间应加空行。 1.6 空格 在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空 格;进行非对等操作时,如果是关系密切的立即操作符(如-> ),后不应加空格。采用这种松散方式 编写代码的目的是使代码更加清晰。 由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语 句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为 在C/C++语言中括号已经是最清晰的标志了。 在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留 空格时不要连续留两个以上空格。 (1)逗号、分号只在后面加空格。 int a, b, c; (2)比较操作符, 赋值操作符"="、 "+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符" = MAX_TIME_VALUE) { a = b + c; } a *= 2; a = b ^ 2; (3)"!"、"~"、"++"、"-"、"&"(地址运算符)等单目操作符前后不加空格。 *p = 'a'; // 内容操作"*"与内容之间 flag = !isEmpty; // 非操作"!"与内容之间 p = &mem; // 地址操作"&" 与内容之间 i++; // "++","-"与内容之间 (4)"->"、"."前后不加空格。 p->id = pid; // "->"指针前后不加空格 (5) if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。 if (a >= b && c > d)

1.7对变量的定义,尽量位于函数的开始位置(1)应避免分散定义变量。(2)同一行内不要定义过多变量。(3)同一类的变量在同一行内定义,或者在相邻行定义。(4)数组、指针等复杂类型的定义放在定义区的最后。(5)变量定义区不做较复杂的变量赋值。1.8程序各部分的放置顺序在较小的项目中,按如下顺序组织安排程序各部分:(1)#include。(2)#include”用户自定义的文件”。(3)#define宏定义。(4)全局变量定义。(5)函数原型声明。(6)main函数定义。(7)用户自定义函数。以上各部分之间、用户自定义的函数之间应加空行。注意,函数原型声明统一集中放在main函数之前,不放在某个函数内部。2注释2.1注释的原则和目的注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的一一清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释—一过量的注释则是有害的。注释的自的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。示例:如下注释意义不大。/*ifreceiveflagisTRUE*/if (receive_flag)而如下的注释则给出了额外有用的信息。1* if mtp receive a message from links */if(receive_flag)2.2函数头部应进行注释函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数表)等。示例1:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。/**Function:函数名称Description:Il函数功能、性能等的描述Calls:Ⅱ被本函数调用的函数清单Called By:Ⅱ调用本函数的函数清单Input:I输入参数说明,包括每个参数的作II用、取值说明及参数间关系。Output:I对输出参数的说明。Return:/函数返回值的说明Others:Ⅱ其它说明
1.7 对变量的定义,尽量位于函数的开始位置 (1)应避免分散定义变量。 (2)同一行内不要定义过多变量。 (3)同一类的变量在同一行内定义,或者在相邻行定义。 (4)数组、指针等复杂类型的定义放在定义区的最后。 (5)变量定义区不做较复杂的变量赋值。 1.8 程序各部分的放置顺序 在较小的项目中,按如下顺序组织安排程序各部分: (1)#include 。 (2)#include 〞用户自定义的文件〞。 (3)#define 宏定义。 (4)全局变量定义。 (5)函数原型声明。 (6)main函数定义。 (7)用户自定义函数。 以上各部分之间、用户自定义的函数之间应加空行。注意,函数原型声明统一集中放在main函数之 前,不放在某个函数内部。 2 注释 2.1 注释的原则和目的 注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语 言必须准确、易懂、简洁。通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结 构,使代码成为自注释的——清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要 的注释——过量的注释则是有害的。 注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防 止没必要的重复注释信息。 示例:如下注释意义不大。 /* if receive_flag is TRUE */ if (receive_flag) 而如下的注释则给出了额外有用的信息。 /* if mtp receive a message from links */ if (receive_flag) 2.2 函数头部应进行注释 函数头部应进行注释,列出:函数的目的/ 功能、输入参数、输出参数、返回值、调用关系(函数、 表)等。 示例1:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************* Function: // 函数名称 Description: // 函数功能、性能等的描述 Calls: // 被本函数调用的函数清单 Called By: // 调用本函数的函数清单 Input: // 输入参数说明,包括每个参数的作 // 用、取值说明及参数间关系。 Output: // 对输出参数的说明。 Return: // 函数返回值的说明 Others: // 其它说明

********★********对于某些函数,其部分参数为传入值,而部分参数为传出值,所以对参数要详细说明该参数是入口参数,还是出口参数,对于某些意义不明确的参数还要做详细说明(例如:以角度作为参数时,要说明该角度参数是以弧度(PI),还是以度为单位)对既是入口又是出口的变量应该在入口和出口处同时标明。等等。在注释中详细注明函数的适当调用方法,对于返回值的处理方法等。在注释中要强调调用时的危险方面,可能出错的地方。2.3进行注释时的注意事项(1)建议边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除(2)注释的内容要清楚、明了,含义准确,防止注释二义性。说明:错误的注释不但无益反而有害。3)避免在注释中使用缩写,特别是非常用缩写。在使用缩写时或之前,应对缩写进行必要的说明(4)注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面。除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。示例:如下例子不符合规范。例1:/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].repssn_indexrepssn_ni=ssn_data[index].ni;例2:repssn_ind=ssn_data[index].repssn_index;repssn_ni=ssn_data[index].ni;* get replicate sub system index and net indicator *应如下书写I*get replicate sub system index and net indicator */repssn_ind=ssn_data[index].repssn_index;repssnni=ssndata[index].ni;5)对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须以注释说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。示例:/*activestatistictasknumber*/#defineMAXACTTASKNUMBER1000#defineMAX_ACT_TASKNUMBER1000/*activestatistictasknumber*(6)数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。示例:可按如下形式说明枚举/数据/联合结构。* sccp interface with sccp user primitivemessage name*/enumSCCP_USER_PRIMITIVE1N_UNITDATA_IND, /* sccp notify sccp user unit data come */N_NOTICE_IND,/* sccpnotify usertheNo.7network can not*//*transmissionthismessage*N_UNITDATA_REQ,/*sccpuser'sunitdatatransmissionrequest*/3;(7)全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明
*************************************************/ 对于某些函数,其部分参数为传入值,而部分参数为传出值,所以对参数要详细说明该参数是入口 参数,还是出口参数,对于某些意义不明确的参数还要做详细说明(例如:以角度作为参数时,要说 明该角度参数是以弧度(PI),还是以度为单位),对既是入口又是出口的变量应该在入口和出口处同时标 明。等等。 在注释中详细注明函数的适当调用方法,对于返回值的处理方法等。在注释中要强调调用时的危险 方面,可能出错的地方。 2.3 进行注释时的注意事项 (1)建议边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的 注释要删除。 (2)注释的内容要清楚、明了,含义准确,防止注释二义性。说明:错误的注释不但无益反而有害。 (3)避免在注释中使用缩写,特别是非常用缩写。在使用缩写时或之前,应对缩写进行必要的说明。 (4)注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不 可放在下面。除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。 示例:如下例子不符合规范。 例1: /* get replicate sub system index and net indicator */ repssn_ind = ssn_data[index].repssn_index; repssn_ni = ssn_data[index].ni; 例2: repssn_ind = ssn_data[index].repssn_index; repssn_ni = ssn_data[index].ni; /* get replicate sub system index and net indicator */ 应如下书写 /* get replicate sub system index and net indicator */ repssn_ind = ssn_data[index].repssn_index; repssn_ni = ssn_data[index].ni; (5)对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释, 说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。 示例: /* active statistic task number */ #define MAX_ACT_TASK_NUMBER 1000 #define MAX_ACT_TASK_NUMBER 1000 /* active statistic task number */ (6)数据结构声明( 包括数组、结构、类、枚举等) ,如果其命名不是充分自注释的,必须加以注释。 对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右 方。 示例:可按如下形式说明枚举/数据/联合结构。 /* sccp interface with sccp user primitive message name */ enum SCCP_USER_PRIMITIVE { N_UNITDATA_IND, /* sccp notify sccp user unit data come */ N_NOTICE_IND, /* sccp notify user the No.7 network can not */ /* transmission this message */ N_UNITDATA_REQ, /* sccp user's unit data transmission request*/ }; (7)全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意 事项等的说明

示例:/*TheErrorCodewhenSCCPtranslate*/*GlobalTitlefailureasfollows*///变量作用、含义/*0-SUCCESS1-GTTableerror*/*2-GTerrorOthers-nouse*/1变量取值范围* only function SCCPTranslateO in *//*thismodual canmodifyit,andother*/I* module can visit it through call *//*thefunctionGetGTTransErrorCode*///使用方法BYTEg_GTTranErrorCode;8)注释与所描述内容进行同样的缩排,让程序排版整齐,并方便注释的阅读与理解。示例:如下例子,排版不整齐,阅读稍感不方便。voidexample fun(void)1/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlock Two1应改为如下布局。voidexample fun(void)1/*codeonecomments*/CodeBlockOne/*codetwocomments*CodeBlockTwo}(9)将注释与其上面的代码用空行隔开。示例:如下例子,显得代码过于紧凑。* code one comments */program codeone/*codetwocomments*/programcodetwo应如下书写I* code one comments */program codeone/*codetwocomments*/programcodetwo(10)对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。(11)对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理(即上一个case后无break),必须在该case语句处理完、下一个case语句前加上明确的注释,以清楚表达程序编写者的意图,有效防止无故遗漏break语句(可避免后期维护人员对此感到迷惑:原程序员是遗漏了break语句还是本来就不应该有)。示例:case CMD_DOWN:ProcessDown);break;
示例: /* The ErrorCode when SCCP translate */ /* Global Title failure, as follows */ // 变量作用、含义 /* 0 - SUCCESS 1 - GT Table error */ /* 2 - GT error Others - no use */ // 变量取值范围 /* only function SCCPTranslate() in */ /* this modual can modify it, and other */ /* module can visit it through call */ /* the function GetGTTransErrorCode() */ // 使用方法 BYTE g_GTTranErrorCode; (8)注释与所描述内容进行同样的缩排,让程序排版整齐,并方便注释的阅读与理解。 示例:如下例子,排版不整齐,阅读稍感不方便。 void example_fun( void ) { /* code one comments */ CodeBlock One /* code two comments */ CodeBlock Two } 应改为如下布局。 void example_fun( void ) { /* code one comments */ CodeBlock One /* code two comments */ CodeBlock Two } (9)将注释与其上面的代码用空行隔开。 示例:如下例子,显得代码过于紧凑。 /* code one comments */ program code one /* code two comments */ program code two 应如下书写 /* code one comments */ program code one /* code two comments */ program code two (10)对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。这些语句往往是程序实现某一 特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文 档。 (11)对于switch 语句下的case 语句,如果因为特殊情况需要处理完一个case 后进入下一个case 处理 (即上一个case后无break),必须在该case 语句处理完、下一个case 语句前加上明确的注释,以清 楚表达程序编写者的意图,有效防止无故遗漏break语句(可避免后期维护人员对此感到迷惑:原程序 员是遗漏了break语句还是本来就不应该有)。示例: case CMD_DOWN: ProcessDown(); break;

caseCMD_FWD:ProcessFwdO;if (...)1break;Jelse1ProcessCFW_B(;IlnowjumpintocaseCMD_A1case CMD_A:ProcessA();break;(12)在程序块的结束行右方加注释标记,以表明某程序块的结束。当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。示例:参见如下例子。if (...)Tprogramcodewhile (index<MAX INDEX)1programcode}/*endofwhile(index<MAX_INDEX)*/I/指明该条while语句结束}/*endofif(..)*/I/指明是哪条if语句结束(13)在顺序执行的程序中,每隔3一5行语句,应当加一个注释,注明这一段语句所组成的小模块的作用。对于自己的一些比较独特的思想要求在注释中标明。(14)注释格式尽量统一,建议使用"*....*。(15)注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达一一注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。3命名规则C是一门朴素的语言,你使用的命名也应该这样。与Modula-2和Pascal程序员不同,C程序员不使用诸如"ThisVariablelsATemporaryCounter"这样"聪明"的名字。C程序员应该叫它"tmp",这写起来更简单,也不会更难懂。然而,当面对复杂情况时就有些棘手,给全局变量取一个描述性的名字是必要的。把一个全局函数叫做"foo"是一种目光短浅的行为。全局函数也一样,如果你有一个统计当前用户个数的函数,应当把它命名为"count_active_userO"或者简单点些的类似名称,不应该命名为"cntusrO"。3.1三种流行的命名法则目前,业界共有四种命名法则:驼峰命名法、匈牙利命名法、帕斯卡命名法和下划线命名法,其中前三种是较为流行的命名法。(1)驼峰命令法。正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。例如,下面是分别用骆驼式命名法和下划线法命名的同一个函数:printEmployeePaychecks();print_employee_paychecks0);第一个函数名使用了驼峰命名法,函数名中的每一个逻辑断点都有一个大写字母来标记。第二个函数名使用了下划线法,函数名中的每一个逻辑断点都有一个下划线来标记。驼峰命名法近年来越来越流行了,在许多新的函数库和MicrosoftWindows这样的环境中,它使用得当相多。另一方面,下划线法是C出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中
case CMD_FWD: ProcessFwd(); if (.) { . break; } else { ProcessCFW_B(); // now jump into case CMD_A } case CMD_A: ProcessA(); break; . (12)在程序块的结束行右方加注释标记,以表明某程序块的结束。当代码段较长,特别是多重嵌套 时,这样做可以使代码更清晰,更便于阅读。示例:参见如下例子。 if (.) { program code while (index < MAX_INDEX) { program code } /* end of while (index < MAX_INDEX) */ // 指明该条while语句结束 } /* end of if (.)*/ // 指明是哪条if语句结束 (13)在顺序执行的程序中,每隔3—5行语句,应当加一个注释,注明这一段语句所组成的小模块的作 用。对于自己的一些比较独特的思想要求在注释中标明。 (14)注释格式尽量统一,建议使用"/* . */"。 (15)注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非 能用非常流利准确的英文表达——注释语言不统一,影响程序易读性和外观排版,出于对维护人员 的考虑,建议使用中文。 3 命名规则 C是一门朴素的语言,你使用的命名也应该这样。与Modula-2和Pascal程序员不同,C程序员不使用 诸如"ThisVariableIsATemporaryCounter"这样"聪明"的名字。C程序员应该叫它"tmp",这写起来更简 单,也不会更难懂。 然而,当面对复杂情况时就有些棘手,给全局变量取一个描述性的名字是必要的。把一个全局函数 叫做"foo"是一种目光短浅的行为。全局函数也一样,如果你有一个统计当前用户个数的函数,应当 把它命名为"count_active_user()"或者简单点些的类似名称,不应该命名为"cntusr()"。 3.1 三种流行的命名法则 目前,业界共有四种命名法则:驼峰命名法、匈牙利命名法、帕斯卡命名法和下划线命名法,其中 前三种是较为流行的命名法。 (1)驼峰命令法。正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。 例如,下面是分别用骆驼式命名法和下划线法命名的同一个函数: printEmployeePaychecks(); print_employee_paychecks(); 第一个函数名使用了驼峰命名法,函数名中的每一个逻辑断点都有一个大写字母来标记。第二个函 数名使用了下划线法,函数名中的每一个逻辑断点都有一个下划线来标记。 驼峰命名法近年来越来越流行了,在许多新的函数库和Microsoft Windows这样的环境中,它使用得 当相多。另一方面,下划线法是C出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中

它的使用非常普遍。(2)匈牙利命名法。广泛应用于象MicrosoftWindows这样的环境中。Windows编程中用到的变量(还包括宏)的命名规则为匈牙利命名法,这种命名技术是由一位能干的Microsoft程序员查尔斯-西蒙尼(CharlesSimonyi)提出的。匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域、类型等。这些符号可以多个同时使用,顺序是先m_(成员变量)、再指针、再简单数据类型、再其它。这样做的好处在于能增加程序的可读性,便于对程序的理解和维护。例如:mIpszStr,表示指向一个以o字符结尾的字符串的长指针成员变量。匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀:前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。(3)帕斯卡(pascal)命名法。与驼峰命名法类似,二者的区别在于:驼峰命名法是首字母小写,而帕斯卡命名法是首字母大写,如:Displaylnfo();string UserName;二者都是采用了帕斯卡命名法。(4)三种命名规则的小结:MyData就是一个帕斯卡命名的示例;myData是一个驼峰命名法,它第一个单词的第一个字母小写,后面的单词首字母大写,看起来像一个骆驼;iMyData是一个匈牙利命名法,它的小写的说明了它的型态,后面的和帕斯卡命名相同,指示了该变量的用途。3.2命名的基本原则(1)标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解一一尽量采用采用英文单词或全部中文全拼表示,若出现英文单词和中文混合定义时,使用连字符”“将英文与中文割开。较短的单词可通过去掉"元音"形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。例如:temp->tmp、flag->flg、statistic->stat、increment->inc、message->msg等缩写能够被大家基本认可。(2)命名中若使用特殊约定或缩写,则要有注释说明。应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。(3)自已特有的命名风格,要自始至终保持一致,不可来回变化。个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。(4)对于变量命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、」、k作局部循环变量是充许的。变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如写成),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。(5)除非必要,不要用数字或较奇怪的字符来定义标识符。(6)命名规范必须与所使用的系统风格保持一致,并在同一项目中统一。(7)在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。对接口部分的标识符应该有更严格限制,防止冲突。如可规定接口部分的变量与常量之前加上"模块"标识等8)用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。下面是一些在软件中常用的反义词组。add / removebegin/endcreate/destroyinsert/deletefirst / lastg et / releaseincrement/decrementput / getadd/deletelock/unlockopen/closemin/maxold/newstart/stopnext/previoussource/targetshow/hidesend/receivesource/destination
它的使用非常普遍。 (2)匈牙利命名法。广泛应用于象Microsoft Windows这样的环境中。Windows 编程中用到的变量(还 包括宏)的命名规则为匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯-西蒙尼 (Charles Simonyi) 提出的。 匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域、 类型等。这些符号可以多个同时使用,顺序是先m_(成员变量)、再指针、再简单数据类型、再其 它。这样做的好处在于能增加程序的可读性,便于对程序的理解和维护。 例如:m_lpszStr, 表示指向一个以0字符结尾的字符串的长指针成员变量。 匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母 大写的一个单词或多个单词组合,该单词要指明变量的用途。 (3)帕斯卡(pascal)命名法。与驼峰命名法类似,二者的区别在于:驼峰命名法是首字母小写,而帕斯 卡命名法是首字母大写,如: DisplayInfo(); string UserName; 二者都是采用了帕斯卡命名法。 (4)三种命名规则的小结:MyData就是一个帕斯卡命名的示例;myData是一个驼峰命名法,它第一个 单词的第一个字母小写,后面的单词首字母大写,看起来像一个骆驼;iMyData是一个匈牙利命名法,它 的小写的i说明了它的型态,后面的和帕斯卡命名相同,指示了该变量的用途。 3.2 命名的基本原则 (1)标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避 免使人产生误解——尽量采用采用英文单词或全部中文全拼表示,若出现英文单词和中文混合定义 时,使用连字符"_"将英文与中文割开。较短的单词可通过去掉"元音"形成缩写;较长的单词可取单 词的头几个字母形成缩写;一些单词有大家公认的缩写。例如:temp->tmp、flag->flg、statistic- >stat、increment->inc、message->msg等缩写能够被大家基本认可。 (2)命名中若使用特殊约定或缩写,则要有注释说明。应该在源文件的开始之处,对文件中所使用的 缩写或约定,特别是特殊的缩写,进行必要的注释说明。 (3)自己特有的命名风格,要自始至终保持一致,不可来回变化。个人的命名风格,在符合所在项目 组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风 格)。 (4)对于变量命名,禁止取单个字符(如i 、j 、k. ),建议除了要有具体含义外,还能表明其变量类 型、数据类型等,但i 、j 、k 作局部循环变量是允许的。变量,尤其是局部变量,如果用单个字符表 示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错 时间。 (5)除非必要,不要用数字或较奇怪的字符来定义标识符。 (6)命名规范必须与所使用的系统风格保持一致,并在同一项目中统一。 (7)在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接 时产生冲突。对接口部分的标识符应该有更严格限制,防止冲突。如可规定接口部分的变量与常量 之前加上"模块"标识等。 (8)用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。下面是一些在软件中常用的反 义词组。 add / remove begin / end create / destroy insert / delete first / last g et / release increment / decrement put / get add / delete lock / unlock open / close min / max old / new start / stop next / previous source / target show / hide send / receive source / destination

up / downcut/paste示例:int min_sum;intmax_sum,intadd_user(BYTE*user_name);intdelete_user(BYTE*user_name);9)除了编译开关/头文件等特殊应用,应避免使用EXAMPLETEST之类以下划线开始和结尾的定义。3.3变量名的命名规则(1)变量的命名规则要求用匈牙利法则"。即开头字母用变量的类型,其余部分用变量的英文意思、英文的缩写、中文全拼或中文全拼的缩写,要求单词的第一个字母应大写。即:变量名=变量类型+变量的英文意思(或英文缩写、中文全拼、中文全拼缩写)对非通用的变量,在定义时加入注释说明,变量定义尽量可能放在函数的开始处。见下表:bool用b开头bFlgint用开头iCountshortint用n开头nStepCountlongint用开头ISumchar用c开头cCountunsignedchar用by开头float用f开头fAvgdouble用d开头dDetaunsignedint(WORD)用w开头wCountunsignedlongint(DWORD)用dw开头dwBroad字符串用s开头sFileName用o结尾的字符串用sz开头szFileName(2)指针变量命名的基本原则为:对一重指针变量的基本原则为:"p"+变量类型前缀+命名,如一个float*型应该表示为pfStat。对二重指针变量的基本规则为:"pp"+变量类型前缀+命名。对三重指针变量的基本规则为:"ppp"+变量类型前缀+命名。(3)全局变量用g_开头,如一个全局的长型变量定义为g_IFailCount,即:变量名=g_+变量类型+变量的英文意思(或缩写)。此规则还可避免局部变量和全局变量同名而引起的问题。(4)静态变量用s开头,如一个静态的指针变量定义为s_plPervInst,即:变量名=s+变量类型+变量的英文意思(或缩写)(5)对枚举类型(enum)中的变量,要求用枚举变量或其缩写做前缀。并且要求用大写。如:enumcmEMDAYS8EMDAYS_MONDAY;EMDAYSTUESDAY:J;(6)对struct、union变量的命名要求定义的类型用大写。并要加上前缀,其内部变量的命名规则与变量命名规则一致。结构一般用S开头,如:struct ScmNPoint(intnX;1/点的X位置intnY;I/点的Y位置
cut / paste up / down 示例: int min_sum; int max_sum; int add_user( BYTE *user_name ); int delete_user( BYTE *user_name ); (9)除了编译开关/ 头文件等特殊应用,应避免使用_EXAMPLE_TEST_ 之类以下划线开始和结尾的 定义。 3.3 变量名的命名规则 (1)变量的命名规则要求用"匈牙利法则"。即开头字母用变量的类型,其余部分用变量的英文意思、英 文的缩写、中文全拼或中文全拼的缩写,要求单词的第一个字母应大写。 即: 变量名=变量类型+变量的英文意思(或英文缩写、中文全拼、中文全拼缩写) 对非通用的变量,在定义时加入注释说明,变量定义尽量可能放在函数的开始处。 见下表: bool 用b开头 bFlg int 用i开头 iCount short int 用n开头 nStepCount long int 用l开头 lSum char 用c开头 cCount unsigned char 用by开头 float 用f开头 fAvg double 用d开头 dDeta unsigned int(WORD) 用w开头 wCount unsigned long int(DWORD) 用dw开头 dwBroad 字符串 用s开头 sFileName 用0结尾的字符串 用sz开头 szFileName (2)指针变量命名的基本原则为: 对一重指针变量的基本原则为:"p"+变量类型前缀+命名,如一个float*型应该表示为pfStat。对二重 指针变量的基本规则为:"pp"+变量类型前缀+命名。对三重指针变量的基本规则为:"ppp"+变量类 型前缀+命名。 (3)全局变量用g_开头,如一个全局的长型变量定义为g_lFailCount,即:变量名=g_+变量类型+变量的 英文意思(或缩写)。此规则还可避免局部变量和全局变量同名而引起的问题。 (4)静态变量用s_开头,如一个静态的指针变量定义为s_plPerv_Inst,即: 变量名=s_+变量类型+变量 的英文意思(或缩写) (5)对枚举类型(enum)中的变量,要求用枚举变量或其缩写做前缀。并且要求用大写。如: enum cmEMDAYS { EMDAYS_MONDAY; EMDAYS_TUESDAY; . }; (6)对struct、union变量的命名要求定义的类型用大写。并要加上前缀,其内部变量的命名规则与变 量命名规则一致。 结构一般用S开头,如: struct ScmNPoint { int nX;//点的X位置 int nY; //点的Y位置

1;联合体一般用U开头,如:union UcmLPoint1LONG IX;LONG IY;1(7)对常量(包括错误的编码)命名,要求常量名用大写,常量名用英文表达其意思。当需要由多个单词表示时,单词与单词之间必须采用连字符""连接。如:#defineCM_FILE_NOT_FOUNDCMMAKEHR(OX20B)其中CM表示类别。(8)对const的变量要求在变量的命名规则前加入c_,即:c_+变量命名规则;示例:constchar*c_szFileName;
}; 联合体一般用U开头,如: union UcmLPoint { LONG lX; LONG lY; } (7)对常量(包括错误的编码)命名,要求常量名用大写,常量名用英文表达其意思。当需要由多个单词 表示时,单词与单词之间必须采用连字符"_"连接。 如:#define CM_FILE_NOT_FOUND CMMAKEHR(0X20B) 其中CM表示类别。 (8)对const 的变量要求在变量的命名规则前加入c_,即:c_+变量命名规则;示例: const char* c_szFileName;
按次数下载不扣除下载券;
注册用户24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
- 《计算机程序设计基础》课程学习指南(C语言)C语言常见问题详解.pdf
- 《计算机程序设计基础》课程学习指南(C语言)C语言常见英文单词.pdf
- 《计算机程序设计基础》课程学习指南(C语言)C语言常见错误中英文对照表.pdf
- 《计算机程序设计基础》课程教学大纲 C Programming Language(C语言).pdf
- 《计算机控制系统》课程教学资源(PPT课件)第7章 计算机控制系统设计与实现.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第6章 分布式测控网络技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第5章 计算机控制系统软件设计相关技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第4章 先进控制技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第3章 常规数字控制技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第2章 计算机控制系统硬件设计相关技术.ppt
- 《计算机控制系统》课程教学资源(PPT课件)第1章 计算机控制系统概述.ppt
- 《计算机控制系统》课程教学资源(PPT课件)前言.ppt
- 《计算机控制系统》课程试题试卷(答案).doc
- 《计算机控制系统》课程试题试卷(题目).doc
- 《计算机控制系统》课程教学大纲.pdf
- 《数据结构》课程教学资源(PPT课件)第四章 数组、集合和矩阵.ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.7 树与二叉树的转换 6.8 树的遍历).ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.3 以结点类为基础的二叉树设计 6.4 二叉树类 6.5 线索二叉树 6.6 哈夫曼树).ppt
- 《数据结构》课程教学资源(PPT课件)第六章 树和二叉树(6.1 树 6.2 二叉树).ppt
- 《数据结构》课程教学资源(PPT课件)第八章 排序.ppt
- 《计算机程序设计基础》课程学习指南(C语言)C语言初学者编程规范-2/2.pdf
- 《计算机程序设计基础》课程学习指南(C语言)给C语言初学者的学习建议.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 1 - Introduction.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 2 - Binary Representation.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 4 - Simple Data Types.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 5 - Standard IO.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 6 - Operators, Expressions and Statements.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 7 - Making Decisions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 8 - Looping.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 3 - Hardware and Software.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 9 - Arrays.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 10 - Basics of Pointers.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 11 - Strings.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 12 - Basics of Functions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 13 - More functions.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 14 - Files.pdf
- 英格兰萨里大学:《C语言》课程教学资源(讲义)Lecture 15 - Data Structures.pdf
- 《计算机程序设计基础》课程授课教案(C语言)第1章 C语言概述.pdf
- 《计算机程序设计基础》课程授课教案(C语言)第2章 基本数据类型和运算符.pdf
- 《计算机程序设计基础》课程授课教案(C语言)第3章 控制结构.pdf