2. 文件组织

一个文件包含的各个部分应该用若干个空行分隔。虽然对源文件没有最大长度限制,但超过1000行的文件处理起来非常不方便。编辑器很可能没有足够的临时空间来编辑这个文件,编译过程也会因此变得十分缓慢。与回滚到前面所花费的时间相比,那些仅仅呈现了极少量信息的多行星号是不值得的,我们不鼓励使用。超过79列的行无法被所有的终端都很好地处理,应该尽可能的避免使用。过长的行会导致过深的缩进,这常常是一种代码组织不善的症状。

2.1 文件命名惯例

文件名由一个基础名、一个可选的句号以及后缀组成。名字的第一个字符应该是一个字母,并且所有字符(除了句号)都应该是小写的字母和数字。基础名应该由八个或更少的字符组成,后缀应该由三个或更少的字符组成(四个,如果你包含句号的话)。这些规则对程序文件以及程序使用和产生的默认文件都适用(例如,"rogue.sav")。

一些编译器和工具要求文件名符合特定的后缀命名约定。下面是后缀命名要求:

C源文件的名字必须以.c结尾
汇编源文件的名字必须以.s结尾 

我们普遍遵循以下命名约定:

可重定位目标文件名以.o结尾
头文件名以.h结尾
    在多语言环境中一个可供选择的更好的约定是用语言类型和.h共同作为后缀(例如,"foo.c.h" 或 "foo.ch")。 

Yacc源文件名以.y结尾
Lex源文件名以.l结尾 

C++使用编译器相关的后缀约定,包括.c,..c,.cc,.c.c以及.C。由于大多C代码也是C++代码,因此这里并没有一个明确的方案。

此外,我们一般约定使用"Makefile"(而不是"makefile")作为make(对于那些支持make的系统)工具的控制文件,并且使用"README"作为简要描述目录内容或目录树的文件。

2.2 程序文件

下面是一个程序文件各个组成部分的推荐排列顺序:

文件的第一部分是一个序,用于说明该文件中的内容是什么。对文件中的对象(无论它们是函数,外部数据声明或定义,或是其他一些东西)用途的描述比一个对象名字列表更加有用。这个序可选择地包含作者信息、修订控制信息以及参考资料等。

接下来是所有被包含的头文件。如果某个头文件被包含的理由不是那么显而易见,我们需要通过增加注释说明原因。大多数情况下,类似stdio.h这样的系统头文件应该被放在用户自定义头文件的前面。

接下来是那些用于该文件的defines和typedefs。一个常规的顺序是先写常量宏、再写函数宏,最后是typedefs和枚举(enums)定义。

接下来是全局(外部)数据声明,通常的顺序如下:外部变量,非静态(non-static)全局变量,静态全局变量。如果一组定义被用于部分特定全局数据(如一个标志字),那么这些定义应该被放在对应数据声明后或嵌入到结构体声明中,并将这些定义缩进到其应用的声明的第一个关键字的下一个层次(译注:实在没有搞懂后面这句的含义)。

最后是函数,函数应该以一种有意义的顺序排列。相似的函数应该放在一起。与深度优先(函数定义尽可能在他们的调用者前后)相比,我们应该首选广度优先方法(抽象层次相似的函数放在一起)。这里需要相当多的判断。如果定义大量本质上无关的工具函数,可考虑按字母表顺序排列。

2.3 头文件

头文件是那些在编译之前由C预处理器包含在其他文件中的文件。诸如stdio.h的一些头文件被定义在系统级别,所有使用标准I/O库的程序必须包含它们。头文件还用来包含数据声明和定义,这些数据不止一个程序需要。头文件应该按照功能组织,例如,独立子系统的声明应该放到独立的头文件中。如果一组声明在代码从一种机器移植到另外一种机器时变动的可能性很大,那么这些声明也应该被放在独立的头文件中。

避免私有头文件的名字与标准库头文件的名字一样。下面语句:

#include "math.h"`

当预期的头文件在当前目录下没有找到时,它将会包含标准库中的math头文件。如果这的确是你所期望发生的,那么请加上注释。包含头文件时不要使用绝对路径。当从标准位置获取头文件时,请使用<name>包含头文件;或相对于当前路径定义它们。C编译器的"include-path"选项(在许多系统中为-l)是处理扩展私有库头文件的最好方法,它允许在不改变源码文件的情况下重新组织目录结构。

声明了函数或外部变量的头文件应该被那些定义了这些函数和变量的文件所包含。这样一来,编译器就可以做类型检查了,并且外部声明将总是与定义保持一致。

在头文件中定义变量往往是个糟糕的想法,它经常是一个在文件间对代码进行低劣划分的症状。此外,在一次编译中,像typedef和经过初始化的数据定义无法被编译器看到两次。在一些系统中,重复的没有使用extern关键字修饰的未初始化定义也会导致问题。当头文件嵌套时,会出现重复的声明,这将导致编译失败。

头文件不应该嵌套。一个头文件的序应该描述其使用的其他被包含的头文件的实用特性。在极特殊情况下,当大量头文件需要被包含在多个不同的源文件中时,可以被接受的做法是将公共的头文件包含在一个单独的头文件中。

一个通用的做法是将下面这段代码加入到每个头文件中以防止头文件被意外多次包含。

#ifndef EXAMPLE_H
#define EXAMPLE_H
 ...    /* body of example.h file */
#endif /* EXAMPLE_H */

我们不应该对这种避免多次包含的机制产生依赖,特别是不应该因此而嵌套包含头文件。

2.4 其他文件

还有一个惯例就是编写一个名为"README"的文件,用于描述程序的整体情况以及问题。例如,我们经常在README包含程序所使用的条件编译选项列表以及相关说明,还可以包含机器无关的文件列表等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容