Linux内核编程规范与代码风格 (2)

在声明指针或者返回值为指针的函数时,星号的位置应该紧靠着变量名或函数名,而不是类型名,例如:

char *linux_banner; unsigned long long memparse(char *ptr, char **retptr); char *match_strdup(substring_t *s);

在二元操作符和三元操作符周围添加一个空格,例如:

= + - < > * / % | & ^ <= >= == != ? :

但是不要在一元操作符之后添加空格:

& * + - ~ ! sizeof typeof alignof __attribute__ defined

不要在后缀的自增自减一元操作符之前添加空格:

++ --

不要在前缀的自增自减一元操作符之后添加空格:

++ --

不要在结构体成员操作符周围添加空格:

. ->

不要在行末添加多余的空格。一些编辑器的“智能”缩进会帮你在行首添加一些空格,好让你在下一行可以立即写代码。但是某些编辑器不会帮你把多余的空格给删掉,尽管你已经写完了一行代码。比如你只想留一行空行,但是编辑器却“好心”地帮你填上了一些空格。这样一来,你就在行末添加了多余的空格。

Git 通常会警告你,让你除去这些多余的空格,并且可以帮你删掉这些东西。但是,如果你让 Git 一直帮你这样修补你的代码,这很可能导致代码行的上下错乱,之后的自动修补的失败。

4 命名

C 是一种简洁粗旷的语言,因此,你的命名也应该是简洁的。C 程序员不会像 Modula-2 和 Pascal 程序员那样使用 ThisVariableIsATemporaryCounter 这种“可爱”的名字,一个 C 程序员会把这种变量命名为 tmp ,如此简洁易写。

尽管看到一个混合大小写的名字让人皱眉,不过对于全局变量来说,一个具有描述性的名字还是很有必要的。去调用一个名为 foo 的全局函数同样让人难以接受。

全局变量(只有当你真正需要的时候才用它)和全局函数需要使用描述性的名字。如果你有一个计算活跃用户数量的函数,你应该起这样一个名字 count_active_users() 或者类似的,而不是这样一个名字 cntusr() 。

起一个包含函数类型的名字(匈牙利命名法)是摧残大脑的行为,编译器知道函数的类型并且会检查类型,这样的名字不会起到任何帮助,它仅仅会迷惑程序员。所以,也难怪微软做出了那么多充满了 bug 的程序。

局部变量名应该简短,如果你需要写一个循环,定义一个计数器,在不产生歧义的情况下,你大可命名为 i ,命名为 loop_counter 是生产力很低的行为。同样地,tmp 可以是任何类型的临时变量。

如果你担心会弄混变量名,那么你遇到了另一个问题,你患上了函数增长荷尔蒙失调综合症。

5 Typedefs

请不要使用 vps_t 这种东西,这是 typedef 的错误用法,当你看到

vps_t a;

这种写法时,它究竟是个什么东西?相反,如果是这样的写法

struct virtual_container *a;

你就很容易知道 a 代表着什么。

很多人认为 typedef 是用来帮助提高可读性的,但是事实往往不是这样的。typedef 仅仅有如下用处:

a. 封装对象(typedef 可以方便的隐藏对象)

例如,pte_t 会把对象封装起来,你仅仅只能通过合适的“访问函数”(成员函数)来访问这个对象。

注意:封装和“访问函数”(成员函数)本身就不是好东西,我们使用 pte_t 这种东西的理由就是,它指向的对象本身绝对没有东西可以访问(我们压根儿不使用封装和成员函数那一套)。

b. 指明整数类型,这种抽象可以帮助我们避免一些使用 int 和 long 的疑虑

u8/u16/u32 是完美的使用 typedef 的例子。

注意:你必须要有明确的理由来使用这些用法,如果一些地方使用的本身就是 unsigned long ,那么你没有任何理由这样做

typedef unsigned long myflags_t;

但是如果你有明确的理由来解释为什么在某种情况下使用 unsigned int,而在其他情况下使用 unsigned long,那么大可使用 typedef。

c. 使用 sparse 去新建一个类型来做类型检查

d. 在某些情况下新建一个与 C99 标准相等的类型

尽管只需要花一小段眼睛和大脑的时间来适应新标准的类型,如 uint32_t,但是一些人还是反对使用他们。

因此,你可以使用 Linux 独有的 u8/u16/u32/u64 和他们的有符号版本,也可以使用和他们等价的新标准的类型,他们的使用都不是强制的。

当你所编辑的代码已经使用了某一种版本时,你应该按照原样使用相同的版本。

e. 用户空间中的类型安全

用户空间中的某些特定的结构体中,我们不能使用 C99 定义的新类型以及上述的 u32,取而代之,我们统一使用 __u32 之类的类型。

也许还有其他情况,但是基本的规则就是,如果你不能满足上述其中一条情况,你就永远不要使用 typedef。

通常,一个指针或者一个有可访问元素的结构体,都不应该使用 typedef。

6 函数

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfpsf.html