关于一些C语言编程的一些个人想法

Post by zerob13

首先么,这是个人风格,完全不是权威之说。
第二,记录下来只是感觉自己这样蛮舒服,分享而已。
第三,别拿某为谭姓叫兽的文章来说事情,不解释。
第四,这里的 C 语言不是狭义的指 C 这门语言,也包括 C++,object-c,甚至 Java 等类似与 C语法的语言
────────────────────────────────
好了,下面进入正文。比较琐碎,所以就想到什么讲什么了。
先说说一个判断 0 的问题吧,或者称为判断空值。一般空值常规的来思考分那么几种,NULL,0,0.0 以及 false(可能还有别的,但是常规就这些了,所以就讲这些)。那么这些分别有什么区别呢?
首先说说,写判 0 的风格是为了什么,因为 C 语言可以直接用这么一句话来表示几乎所有的空值
if(!a){}
那么,我要把判 0 的语句分开写,就是为了区别变量的类型,方便阅读代码
倒过来讲,先解释 false 的变量,一般这个变量都是布尔型的变量,那么这个变量就两个值,真或者假。所以我一般选择上面那种
if(!a){}
的方式来表示这个变量为假的时候执行什么。理由吧,个人偏好,也有一点认为,!作为一个逻辑运算符,而布尔是逻辑变量,所以凑在一起刚刚好。
然后是 0.0,这一般指 float 或者 double 的变量,这种变量的一个特点就是不精确。如果你直接用
if(a==0.0){}
之类的方法来表述,可能会出现不可意料的问题。所以这里我也选择一种比较流行的处理方法,就是让一个实型变量和一个极小的误差值 EPS 做比较。比如如下代码:

<br></br>
#define EPS 1e-9<br></br>
if(fabs(a-0.0)<eps><br></br>
就是这种方式,对于一个实型变量,最好把相等的比较转化成为大于小于的比较,原因么,不赘述了,学过组成原理就知道了。<br></br>
整数变量不多说,最常规的方法<br></br><br></br>
if(a==0)<br></br>
{}<br></br><br></br>
然后是指针一类的,空值为 NULL 的,大家都知道 NULL 就是 0,但是书写的时候,还是最好把 NULL 写上了,这样可读性大大的增加。例:<br></br><br></br>
if(a==NULL)<br></br>
{}<br></br><br></br>
判断0的问题大约就想到那么一些,然后说说几个小点。<br></br>
第一个是一个规范问题,一般很多人都喜欢把函数声明和实现都放在一起。特别是类的成员函数,别的函数也一样。其实这个习惯不是很好,C语言也好,C++ 也好,都分为 .h 和 .c(.cpp) 两种文件,一般 .h 文件里面放声明,.c 文件里面放实现,包括成员函数。这个主要是方便别的利用你代码的人方便,不需要繁杂的翻看你的整个实现,只要看 .h 文件就可以对你的函数如何使用一目了然。<br></br>
第二个是一个小细节,就是 void 参数的使用,这里说的不是<br></br><br></br>
void main()<br></br><br></br>
个人是很反对这种写法的,因为 main() 函数作为系统直接调用的函数,你如果不返回一个值给系统,系统怎么知道你的程序是正常还是不正常的结束的?个人感觉,我很反感用 void 来声明 main() 函数。<br></br>
那么,这里的 void 指什么呢?就是指没有参数表的函数,希望在函数的参数表里面填写一个 void <del datetime="2010-12-25T06:58:19+00:00">原因吧,难说,这样写的确我说不上特别的好处,但是感觉会舒服很多,可能就是一个个人偏好吧。</del>,原因是,加了void后,这个函数就被限制成为不能传入任何参数的函数了,如果你强行传入参数,编译会失败。如果不加在 C语言会认为这个函数可以传入任何参数的函数,区别还是很大的。(感谢蔡大牛提醒)。<br></br><br></br>
int GetOne(void)<br></br>
{<br></br>
    return 1;<br></br>
}<br></br><br></br>
第三点 就是解释一下 char* strcpy(char*,char*); 这个函数的返回值,然后抛砖引玉的来说说返回值的重要性。这里也许有些朋友会费解,明明 strcpy 的返回值已经给了第一个参数了,为什么还要最后 return 回来?这个不是“脱了裤子放屁──多此一举”么。其实不然,我们看如下代码就明白为什么了。<br></br><br></br>
int length =strlen (strcpy(str,"zerob13"));<br></br><br></br>
这个返回值就是为了这样的灵活性而考虑设计的,所以设计一个好的返回值对于一个好的函数也是非常重要的。<br></br>
第四点,也是介绍一个神气的东西,叫做空循环。也许很多人学了c语言后一直不理解,为什么还要有个 do-while 循环,感觉有 while 不是已经够了么,这个东西似乎有点多此一举,其实不然。大家都知道,C语言是为了系统而出现的语言,这个 do-while 也自然和这个挂钩了。比如,你总是能够在 linux 的内核里面看到类似如下的宏。<br></br><br></br>
#define DUMP_WRITE(addr,nr) do{memcpy(bufp,addr,nr);bufp+=nr;}while(0)<br></br><br></br>
总所周知,do-while 是先执行后判断循环,这里的while(0)也就是这个代码等价于:<br></br><br></br>
#define DUMP_WRITE(addr,nr)  memcpy(bufp,addr,nr);bufp+=nr;<br></br><br></br>
那么,我们为什么要套上这么一个 do-while 空循环呢?显然不行,一个小例子就可以说明,比如这个<br></br><br></br>
if(OK)<br></br>
  DUMP_WRITE(addr,nr);<br></br>
else<br></br>
 break;<br></br><br></br>
如果,没有空循环,代码会变成这样子。<br></br><br></br>
if(OK)<br></br>
 memcpy(bufp,addr,nr);<br></br>
 bufp+=nr;;<br></br>
else<br></br>
 break;<br></br><br></br>
然后,就悲剧了。但是,当你加上了 do-while 空循环的时候,整个循环被当作单独的一句语句,这样就可以达到正确的效果,如下:<br></br><br></br>
if(OK)<br></br>
do{<br></br>
 memcpy(bufp,addr,nr);<br></br>
 bufp+=nr;<br></br>
}while(0);<br></br>
else<br></br>
 break;<br></br></eps>```