函数应该短小精悍,一个函数只干一件事。一个函数的代码两个屏幕就应该装得下(ISO/ANSI标准屏幕大小是80x24),简单说就是,做一件事并且把它做好。
数的最大长度与函数的复杂度和缩进程度成反比,所以,如果你有一个简单的函数,函数里面只是需要处理一个又一个的 case,每个 case 只是干一些小事,函数长度长一些也没关系。
然而,如果你的函数十分复杂,你怀疑一个不像你一样天才的高中生看不懂,你应该遵守函数最大的长度的限制,使用一些有描述性名称的辅助函数。如果你认为函数的性能至关重要,你可以让编译器把这些辅助函数编译成内联函数,一般情况下编译器可以比你做得更好。
另一个测量函数的因素是局部变量的数量,他们不应该超出5-10个这个范围,否则你就犯了一些错误。重新思考这个函数,把它拆分成更小的几段。人类的大脑一般只能同时关注七件不同的事,更多需要关注的事情意味着更多的困扰。尽管你认为你是个天才,但是你也希望理解一段你两周之前写的代码。
在源文件中,用一个空行分割不同的函数,如果函数需要导出到外部使用,那么它对应的 EXPORT 宏应当紧随在函数之后,例如:
int system_is_up(void) { return system_state == SYSTEM_RUNNING; } EXPORT_SYMBOL(system_is_up);函数原型中,参数名应该与参数类型引起写出来,尽管 C 语言允许只写上参数类型,但是我们更推荐参数名,因为这是一种为读者提供有价值信息的简单方式。
不要在函数原型之前使用extern关键字,因为这是不必要且多余的。
7 集中函数出口尽管许多人反对,但是 goto 语句频繁地以无条件跳转的形式被编译器使用。
当函数有多个出口,并且返回之前需要做很多相似的工作时,比如清理空间,这时候 goto 语句是十分方便的。当然了,如果没有类似的清理工作要在返回之前做,那么直接返回即可。
根据 goto 的作用来决定一个 label 的名字,如果 goto 语言要去释放缓存,那么out_free_buffer:会是一个好名字。避免使用 GW-BASIC 的命名方式,比如 err1: err2:,因为当你需要新加或者删除某些函数出口时,你就需要重新排列标签数字,这会让代码的正确性难以得到保证。
使用 goto 的理由如下:
无条件跳转易于理解和阅读
可以减少嵌套
可以减少修改个别函数出口代码所造成的错误
算是帮助编译器做了一些优化的工作
int fun(int a) { int result = 0; char *buffer; buffer = kmalloc(SIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; if (condition1) { while (loop1) { ... } result = 1; goto out_free_buffer; } ... out_free_buffer: kfree(buffer); return result; }一个常见的 bug 被称作 one err bug,它长得像这样:
err: kfree(foo->bar); kfree(foo); return ret;bug 在于某些 goto 语句跳转到此时,foo 仍然是 NULL,修复此 bug 的简单方式就是将一个 label 拆分成两个,err_free_bar: 和 err_free_foo::
err_free_bar: kfree(foo->bar); err_free_foo: kfree(foo); return ret;事实上,你应该进行测试,模拟错误情况的发生,测试所有的出口代码。
8 注释注释是好的,但是要避免过分注释。永远不要去尝试解释你的代码如何工作,而是花时间在写出好的代码来,解释一段烂代码是浪费时间。
一般来说,你应该去说明你的代码做了什么,而不是怎么做。同样地,尽量避免在函数体内写注释,如果你的函数如此复杂,以致于你需要在函数体内分几段注释来解释,那么你应该回到第六节去看看。你可以写一小段的注释来标记或者提醒大家哪些地方写得真聪明(或者真烂),但是不要做得太过分。除此之外,你应该把注释写在函数开头,告诉人们这个函数干了什么,为什么要这样干。
当你给 kernel API 进行注释的时候,请你使用 kernel-doc 的格式。具体参见 https://www.kernel.org/doc/html/latest/doc-guide/index.html#doc-guide
多行注释推荐的格式如下:
/* * This is the preferred style for multi-line * comments in the Linux kernel source code. * Please use it consistently. * * Description: A column of asterisks on the left side, * with beginning and ending almost-blank lines. */对于在 net/ 和 drivers/net/ 中的文件,推荐的多行注释格式如下:
/* The preferred comment style for files in net/ and drivers/net * looks like this. * * It is nearly the same as the generally preferred comment style, * but there is no initial almost-blank line. */