废话篇:本文由CSUST的FINAL实验室的LX创作,用途是给予CSUST的小鲜肉们一些关于C语言代码规范的一些基本知识,若本文有什么错误或是表述不清之处,欢迎留言讨论指正。
代码规范:
在讲代码规范之前,我想给大家看一句感人肺腑的注释名言来告诫各位以后的优秀程序猿:
//When I wrote this, only God and I understood what I was doing.
//Now, God only knows.
在写第一行代码前,我希望大家思考一个问题,在第一行我们应该写什么?我相信大部分的初学者都会写:
#include <stdio.h>
///来一个有奖问答题
///这个头文件stdio的意义是什么?(提示:可以分成三个单词的简写)
有问题吗?答案是没有的。这样写的确是没有任何问题,但是。。。不够骚气。开个玩笑,不过我还是希望有人会喜欢在开始会写上注释,来表明这些代码的大概内容,作者,版权所有翻版必究(雾)
在C语言中基本上有两种注释方式如下
//单行注释
//每次换行都要在最前面加上//
/*多行注释
巴拉巴拉
以这个结尾->*/
可以看到一种是单行注释,即每行注释前都要在最前方加上//,换种说法就是如果在最前方看到了//,无论这行的内容有什么,都属于注释范畴不会被编译。
第二种是多行注释,又称作块注释,这样就可以愉快的在/*与*/间加入你想要写的任意注释,也就是在这块区域里的内容都回在编译时略过。
然而我想说,上面这种多行注释,事实上并不够骚(雾),事实上根据代码规范,应该像下面这样写:
/* 以"/* "开头
* 中间的注释以" * "开头
*///以" */"结尾(之所以这一段是 "*///"开头的原因是因为"*/"之后的就不算作注释内容了)
但是要注意,多行注释不能嵌套,例如下面这样:
/*
巴拉巴拉
/*
巴拉巴拉
*/
巴拉巴拉
*/
很明显,编译器把第二个/*当成了注释来对待,当遇到了第一个*/时,便认为第一个*/对应的是第一个/*,而中间的/*是注释。这样第二个*/找不到一个匹配的/*,所以存在问题。
学了这些这时候我们可以试着写出一个比较像样子的代码注释了:
/*
* 标题:C代码规范
* 作者:CSUST LX
* 巴拉巴拉
* 日期:2018/8/10
* 本文意义:巴拉巴拉
*/
这样你就可以愉快的和你那没看过这种酷酷的注释的室友装逼了,是不是很棒呀?
当然注释的意义不是为了装X,在实际工程中,一个大型项目可能会由很多人接手,或者随着软件的更新换代,代码会交给其他的同事去使用、学习或者是改进,如果你写的乱七八糟又没有注释,或者这地方逻辑很绕却没有注释等,会让你的合作者感到十分困惑且痛苦。除此之外,对于自己而言,虽然说是自己写的代码,但是过了很久之后难免会忘记,因此写一个注释来概括代码的作用、解释某个函数的参数作用以及函数的意义等是十分有意义的。后还是会有很大的好处的。
举个例子,大家可以看一下下面这段代码:
int Fuc( char* a, char* b )
{
int ret = 0 ;
while( ( !(ret = *a - *b) && *b))
++a, ++b;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
给大家看十秒钟,我相信,大家还是一头雾水吧。不过,我也是看的一头雾水呢!
不过如果我给你看的是下面这段代码呢?
///判断两个字符串是否相同
int Fuc( char* a, char* b )
{
int ret = 0 ;
while( ( !(ret = *a - *b) && *b))
++a, ++b;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
是不是感觉瞬间知道了这个函数是干什么用的了呢?
但是,如果你没学过这个函数的话,你又怎么知道这个函数的返回值和它的参数具体是怎样的呢?
如果是像下面一样的话,是不是很快就能明白这个函数的具体用法了呢?
/// 本函数用于比较字符串a与字符串b是否相同
/// 参数a与参数b:要比较的字符串的首地址
/// 返回值:当a<b时,返回为负数;当a==b时,返回值= 0;当a>b时,返回正数。
另外,如果这段函数的名字我改动一下的话,是否也能够很快知道这个函数大概是干什么用的呢?
int strcmp( char* str1, char* str2 )
{
int ret = 0 ;
while( ( !(ret = *str1 - *str2) && *str2))
++str1, ++str2;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
你们应该发现了吧!这个其实是头文件<string.h>里的一个函数strcmp,大家应该多多少少接触到过,这个函数名字是string(字符串)和compare(比较)的缩写结合,有这样一个函数名的话,是不是感觉看起来就很容易理解呢?
下面给大家几个函数名大家来猜猜是干什么的:
int StrToInt(char strData[]);
Girlfriend CreatAGirlfriend();
int find_max_value(int data[]);
从上面的命名里,我们看到了三种常见的命名规范:
1. 驼峰命名法:驼峰命名法就是当变量名或函数名是由一个或多个单词连结在一起时,第一个单词以小写字母开始;从第二个单词开始以后的每个单词的首字母都采用大写字母。(例如:myName,hisBoyfriend)
2. 帕斯卡命名法:帕斯卡命名法就是当变量名或函数名是由一个或多个单词连结在一起时,每个单词的首字母都采用大写字母。(例如:MyName,HisBoyfriend)
3.下划线命名法:所有字母均小写,每个单词间以下划线分割。(例如:my_name,his_name)<