Linux内核代码风格

合集下载

Linux Kernel Coding Style

Linux Kernel Coding Style

a g e1ContentsLinux Kernel Coding Style (Linux 内核代码风格) (2)Chapter 1: Indentation (缩进) ............................................................................................ 2 Chapter 2: Breaking long lines and strings (把长的行和字符串打散) ..................................... 4 Chapter 3: Placing Braces (大括号和空格的放置) ............................................................ 4 3.1 Spaces (空格) ................................................................................................................ 6 Chapter 4: Naming (命名) .................................................................................................. 8 Chapter 5: Typedefs .................................................................................................................. 9 Chapter 6: Functions (函数) ............................................................................................. 11 Chapter 7: Centralized exiting of functions (集中的函数退出途径) ...................................... 12 Chapter 8: Commenting (注释) ............................................................................................... 13 Chapter 9: You've made a mess of it (你已经把事情弄糟了) ................................................ 15 Chapter 10: Kconfig configuration files (Kconfig 配置文件) ................................................ 16 Chapter 11: Data structures (数据结构) ................................................................................. 17 Chapter 12: Macros, Enums and RTL (宏,枚举和RTL ) .................................................. 18 Chapter 13: Printing kernel messages (打印内核消息) .......................................................... 19 Chapter 14: Allocating memory (分配内存) ........................................................................... 20 Chapter 15: The inline disease (内联弊病) ............................................................................. 21 Chapter 16: Function return values and names (函数返回值及命名) ................................... 22 Chapter 17: Don't re-invent the kernel macros (不要重新发明内核宏) ............................... 23 Chapter 18: Editor modelines and other cruft (编辑器模式行和其他需要罗嗦的事情) ..... 24 Appendix I: References .. (24)a g e2Linux Kernel Coding Style (Linux 内核代码风格)This is a short document describing the preferred coding style for the linux kernel. Coding style is very personal, and I won't _force_ my views on anybody, but this is what goes for anything that I have to be able to maintain, and I'd prefer it for most other things too. Please at least consider the points made here.这是一个简短的文档,描述了linux 内核的首选代码风格。

linux系统基础知识

linux系统基础知识

linux系统基础知识Linux系统基础知识Linux是一种自由和开放源代码的类Unix操作系统,它是由Linus Torvalds在1991年首次发布的。

Linux系统具有高度的可定制性和灵活性,因此在服务器、超级计算机、移动设备等领域得到了广泛的应用。

本文将介绍Linux系统的基础知识,包括Linux的发行版、文件系统、用户和权限、命令行和图形界面等方面。

一、Linux的发行版Linux系统有许多不同的发行版,每个发行版都有自己的特点和用途。

常见的Linux发行版有Ubuntu、Debian、Fedora、CentOS、Red Hat等。

这些发行版都是基于Linux内核开发的,但它们的软件包管理、安装方式、默认桌面环境等方面有所不同。

选择适合自己的Linux发行版可以提高工作效率和使用体验。

二、文件系统Linux系统的文件系统采用树形结构,根目录为/。

在根目录下有许多子目录,如bin、etc、home、usr等。

其中,/bin目录存放系统命令,/etc目录存放系统配置文件,/home目录存放用户的主目录,/usr目录存放系统软件和库文件等。

Linux系统支持多种文件系统,如ext4、NTFS、FAT32等。

文件系统的选择取决于使用场景和需求。

三、用户和权限Linux系统是一个多用户系统,每个用户都有自己的用户名和密码。

用户可以通过命令行或图形界面登录系统,并执行各种操作。

Linux 系统采用权限控制机制,每个文件和目录都有自己的权限。

权限分为读、写、执行三种,分别对应数字4、2、1。

文件和目录的权限可以通过chmod命令进行修改。

Linux系统还有超级用户root,拥有系统的最高权限,可以执行任何操作。

四、命令行Linux系统的命令行界面是其最基本的界面,也是最强大的界面。

通过命令行可以执行各种操作,如创建文件、修改权限、安装软件等。

Linux系统的命令行界面有许多命令,如ls、cd、mkdir、rm、chmod等。

linux 内核编译编译选项

linux 内核编译编译选项

1.Code maturity level options代码成熟等级。

此处只有一项:prompt for development and/or incomplete code/drivers,如果你要试验现在仍处于实验阶段的功能,就必须把该项选择为Y了;否则可以把它选择为N。

2. Loadable module support对模块的支持。

这里面有三项:Enable loadable module support:除非你准备把所有需要的内容都编译到内核里面,否则该项应该是必选的。

Set version inFORMation on all module symbols:可以不选它。

Kernel module loader:让内核在启动时有自己装入必需模块的能力,建议选上。

3. Processor type and featuresCPU类型。

有关的几个如下:Processor family:根据你自己的情况选择CPU类型。

High Memory Support:大容量内存的支持。

可以支持到4G、64G,一般可以不选。

Math emulation:协处理器仿真。

协处理器是在386时代的宠儿,现在早已不用了。

MTTR support:MTTR支持。

可不选。

Symmetric multi-processing support:对称多处理支持。

除非你富到有多个CPU,否则就不用选了。

4. General setup这里是对最普通的一些属性进行设置。

这部分内容非常多,一般使用缺省设置就可以了。

下面介绍一下经常使用的一些选项:Networking support:网络支持。

必须,没有网卡也建议你选上。

PCI support:PCI支持。

如果使用了PCI的卡,当然必选。

PCI access mode:PCI存取模式。

可供选择的有BIOS、Direct和Any,选Any 吧。

Support for hot-pluggabel devices:热插拔设备支持。

Linux 汇编语言开发指南

Linux 汇编语言开发指南

二、Linux 汇编语法格式绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。

但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:1.在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。

例如:2.在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。

例如:3.AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。

在Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。

例如:4.在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。

例如:5.在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。

6.远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为"ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即:7.与之相应的远程返回指令则为:8.在 AT&T 汇编格式中,内存操作数的寻址方式是section:disp(base, index, scale)而在 Intel 汇编格式中,内存操作数的寻址方式为:section:[base + index*scale + disp]由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:disp + base + index * scale下面是一些内存操作数的例子:三、Hello World!真不知道打破这个传统会带来什么样的后果,但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串 "Hello World!",那我们也以这种方式来开始介绍 Linux 下的汇编语言程序设计。

Linux的特点及发展趋势

Linux的特点及发展趋势

5.支持多种硬件平台的操作系统
从普通的PC机到高端的超级并行计算机系统,都可以运行Linux系统。 Linux符合IEEE POSIX标准,特别注重可移植性,使Unix下的许多应用程 序可以很容易地移植到Linux平台上,相反也是这样。
6.完整的开发平台
Linux支持一系列的开发工具,几乎所有的主流程序设计语言都已移 植到Linux上,并可免费得到,如 C、C++、PASCAL、Java、Perl、PHP、 Fortran、ADA等。
2013年9月11日星期三
3
间受到很大的限制。在这种情况下,我们不能不为中国软件产业的前途 担忧。 如果我们国家整个信息系统(包括电子政务、电子商务、军事网络 以及互联网等系统)是建立在这样一个平台上,那么我们的政治、经济、 安全等利益如何能得到保障? 为了摆脱这种困境,我们需要有一个自主的操作系统平台。20世纪 80年代,我国曾试图开发过多种操作系统(如COSIX),但后来均因为 缺乏应用软件的支持而没有成功。其实,那时美国IBM公司也曾开发过 一个名为OS/2的操作系统,当时其技术水平甚至超过了微软公司同期的 版本,但同样因为缺乏应用软件,不得不以失败告终。可见,作为服务 器和桌面计算机应用的通用操作系统并不是短期可以成熟的。任何公司、 任何国家,不管投入有多大,要想在短时间里做出一个成熟的通用操作 系统是不现实的。 正当人们为摆脱软件垄断而一筹莫展时,Linux等开放源码软件给我 们带来了希望。Linux系统源代码开放的特点,使得对于安全要求较高的 应用可以认真检查、修改其源代码满足特殊应用需求,而丰富的应用软 件又可以避免前车之鉴。
2.
强大的图形操作界面
Linux系统有着功能强大的图形操作界面,其外观和操作与Microsoft Windows系列非常类似,熟悉Windows操作的用户可以很快掌握其操作方 法。但从技术上来看,Linux操作系统的图形界面与Microsoft Windows系 列有着本质的不同,它是从Unix平台上X Window发展而来,称为XFree86, 这一技术的特点是图形系统分为服务器和客户端两

想要成为Linux底层驱动开发高手这些技巧绝对不能错过

想要成为Linux底层驱动开发高手这些技巧绝对不能错过

想要成为Linux底层驱动开发高手这些技巧绝对不能错过对于想要成为Linux底层驱动开发高手的人来说,掌握一些关键技巧是非常重要的。

本文将介绍一些不能错过的技巧,帮助读者提升自己在Linux底层驱动开发领域的能力。

1. 深入理解Linux内核:在成为Linux底层驱动开发高手之前,你需要对Linux内核有深入的理解。

了解内核的基本概念、代码结构和内核模块之间的关系是非常重要的。

阅读Linux内核的源代码、参与内核邮件列表的讨论以及阅读相关的文献资料都是提升自己技能的好途径。

2. 熟悉底层硬件知识:作为底层驱动开发者,你需要熟悉底层硬件的工作原理。

这包括了解处理器架构、设备的寄存器操作、中断处理等。

掌握底层硬件知识可以帮助你编写高效、稳定的驱动程序。

3. 学习使用适当的开发工具:在Linux底层驱动开发中,使用适当的开发工具是非常重要的。

例如,使用调试器可以帮助你快速定位驱动程序中的问题。

掌握使用GCC编译器、GNU调试器(GDB)和性能分析工具(如OProfile)等工具可以提高你的开发效率。

4. 阅读相关文档和源代码:Linux底层驱动开发涉及到大量的文档和源代码。

阅读设备供应商提供的文档、Linux内核源代码以及其他相关文献资料可以帮助你更好地了解特定设备的工作原理和使用方法。

5. 编写清晰、高效的代码:编写清晰、高效的代码对于成为Linux底层驱动开发高手是至关重要的。

使用良好的编码风格、注释和命名规范可以提高代码的可读性。

此外,了解Linux内核的设计原则和最佳实践也是编写高质量驱动程序的关键。

6. 多实践、调试和优化:在实际开发过程中,积累经验是非常重要的。

通过多实践、调试和优化不同类型的驱动程序,你可以更好地理解Linux底层驱动开发的技巧和要点。

此外,学会使用内核调试工具和性能分析工具可以帮助你提高驱动程序的质量和性能。

7. 参与开源社区:参与开源社区是成为Linux底层驱动开发高手的好方法。

C语言GNU扩展语法

C语言GNU扩展语法

GNU C 9条扩展语法GNC CC是一个功能非常强大的跨平台C编译器,它对标准C语言进行了一系列扩展,以增强标准C的功能,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。

本文把支持GNU扩展的C语言称为GNU C。

Linux内核代码使用了大量的GNU C扩展,以至于能够编译Linux内核的唯一编译器是GNU CC,以前甚至出现过编译Linux内核要使用特殊的GNU CC版本的情况。

本文是对Linux内核使用的GNU C扩展的一个汇总,希望当你读内核源码遇到不理解的语法和语义时,能从本文找到一个初步的解答,更详细的信息可以查看。

文中的例子取自Linux 2.4.18。

1、零长度和变量长度数组组长度为1,分配时计算对象大小比较复杂。

3、语句表达式GNU C把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本只能在复合语句中使用。

例如:复合语句的最后一个语句应该是一个表达式,它的值将成为这个语句表达式的值。

这个定义计算x和y分别两次,当参数有副作用时,将产生不正确的结果,使用语句表达式只计算参数一次,避免了可能的错误。

语句表达式通常用于宏定义。

4、typeof 关键字使用前一节定义的宏需要知道参数的类型,利用typeof可以定义更通用的宏,不必事先这里typeof(x)表示x的值类型,第3行定义了一个与x 类型相同的局部变量_x 并初使化为x,注意第5行的作用是检查参数x和y的类型是否相同。

typeof 可以用在任何类型可以使用的地方,通常用于宏定义。

5、可变参数宏这里arg表示其余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成arg 的值,在宏扩展时替换arg,例如:使用##的原因是处理arg不匹配任何参数的情况,这时arg的值为空,GNU C预处理器在这种特殊情况下,丢弃##之前的逗号,这样扩展为注意最后没有逗号。

源程序书写格式

源程序书写格式

源程序书写格式尽管 C 语言在语法规定上对书写格式没有严格的限制,但是源程序的排版格式应当遵从多数程序员的惯例,以便于程序的维护。

许多同学可能受中文单词间不需要空格的影响以及 C 语言教科书中未对书写格式提出建议,导致书写的 C 语言源程序缺少必要的空格,密密麻麻的语法元素拥挤在一起,阅读起来需要首先“断词”。

按照惯例应当添加适当的空格,断开相关的“语法单词”。

下面列举出书写方面应注意的几个问题。

后面两页附上的源代码样例节选于 Linux 的源程序文件 ping.c ,源代码样例的每行都带有行号,对书写方面应注意的问题提供了实际例子的参考行号。

附表1 C 语言源程序书写格式建议花括号的书写风格有两种:if (xxxxx) {yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy} else {zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}if (xxxxx) { yyyyyyyyyyyyyyy zzzzzzzzzzzzzzzz } else { zzzzzzzzzzzzzzzz zzzzzzzzzzzzzzzz }第一种风格起源于早期 UNIX 的内核源代码,即 C 语言诞生的地方;第二种风格起源于 Pascal 程序员 begin/end 关键字的书写习惯向 C 语言的转变。

目前,在 Microsoft 世界和 Linux 世界中,两种书写风格都很常见,第一种风格略占上风。

无论选择哪种风格必须做到同一个源程序文件中一致,不要两种风格混用。

变量和函数命名方法也有两种风格。

一种是匈牙利命名法(源自 Microsoft 的一位匈牙利籍天才程序员),如:SendAckFrame ;另一种方法为传统的下划线分割法,如:send_ack_frame 。

同一个源程序文件中的命名风格应做到一致。

1 static int in_cksum(unsigned short *buf, int sz)2 {3 int nleft = sz;4 int sum = 0;5 unsigned short *w = buf;6 unsigned short ans = 0;78 while (nleft > 1) {9 sum += *w++;10 nleft -= 2;11 }1213 if (nleft == 1) {14 *(unsigned char *)&ans = *(unsigned char *)w;15 sum += ans;16 }1718 sum = (sum >> 16) + (sum & 0xFFFF);19 sum += (sum >> 16);20 ans = ~sum;21 return ans;22 }2324 static void unpack(char *buf, int sz, struct sockaddr_in *from)25 {26 struct icmp *icmppkt;27 struct iphdr *iphdr;28 struct timeval tv, *tp;29 int hlen, dupflag;30 unsigned long triptime;3132 gettimeofday(&tv, NULL);3334 /* check IP header */35 iphdr = (struct iphdr *) buf;36 hlen = iphdr->ihl << 2;3738 /* discard if too short */39 if (sz < (datalen + ICMP_MINLEN))40 return;4142 sz -= hlen;2243 icmppkt = (struct icmp *) (buf + hlen);44 if (icmppkt->icmp_id != myid)45 return; /* not our ping */4647 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {48 nreceived++;49 tp = (struct timeval *) icmppkt->icmp_data;5051 if ((_usec -= tp->tv_usec) < 0) {52 _sec--;53 _usec += 1000000;54 }55 _sec -= tp->tv_sec;5657 triptime = _sec * 10000 + (_usec / 100);58 tsum += triptime;59 if (triptime < tmin)60 tmin = triptime;61 if (triptime > tmax)62 tmax = triptime;6364 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) {65 nrepeats++;66 nreceived--;67 dupflag = 1;68 } else {69 SET(icmppkt->icmp_seq % MAX_DUP_CHK);70 dupflag = 0;71 }7273 if (options & O_QUIET)74 return;7576 printf("%d bytes from %s: icmp_seq=%u", sz,77 inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),78 icmppkt->icmp_seq);79 printf(" ttl=%d", iphdr->ttl);80 printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);81 if (dupflag)82 printf(" (DUP!)");83 printf("\n");84 }85 }。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CodingStyle/Linux内核代码风格这是一个简短的文档,描述了linux内核的首选代码风格。

代码风格是因人而异的,而且我不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望绝大多数其他代码也能遵守这个风格。

请在写代码时至少考虑一下本文所述的风格。

首先,我建议你打印一份GNU代码规范,然后不要读它。

烧了它,这是一个具有重大象征性意义的动作。

不管怎样,现在我们开始:第一章:缩进制表符是8个字符,所以缩进也是8个字符。

有些异端运动试图将缩进变为4(乃至2)个字符深,这几乎相当于尝试将圆周率的值定义为3。

理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。

尤其是当你盯着你的屏幕连续看了20小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。

现在,有些人会抱怨8个字符的缩进会使代码向右边移动的太远,在80个字符的终端屏幕上就很难读这样的代码。

这个问题的答案是,如果你需要3级以上的缩进,不管用何种方式你的代码已经有问题了,应该修正你的程序。

简而言之,8个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的时候可以给你警告。

留心这个警告。

在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对齐于同一列,而不要“两次缩进”“case”标签。

比如:switch (suffix) {case 'G':case 'g':mem <<= 30;break;case 'M':case 'm':mem <<= 20;break;case 'K':case 'k':mem <<= 10;/* fall through */default:break;}不要把多个语句放在一行里,除非你有什么东西要隐藏:if (condition) do_this;do_something_everytime;也不要在一行里放多个赋值语句。

内核代码风格超级简单。

就是避免可能导致别人误读的表达式。

除了注释、文档和Kconfig之外,不要使用空格来缩进,前面的例子是例外,是有意为之。

选用一个好的编辑器,不要在行尾留空格。

第二章:把长的行和字符串打散代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。

每一行的长度的限制是80列,我们强烈建议您遵守这个惯例。

长于80列的语句要打散成有意义的片段。

每个片段要明显短于原来的语句,而且放置的位置也明显的靠右。

同样的规则也适用于有很长参数列表的函数头。

长字符串也要打散成较短的字符串。

唯一的例外是超过80列可以大幅度提高可读性并且不会隐藏信息的情况。

void fun(int a, int b, int c){if (condition)printk(KERN_W ARNING "Warning this is a long printk with ""3 parameters a: %u b: %u ""c: %u \n", a, b, c);elsenext_statement;}第三章:大括号和空格的放置C语言风格中另外一个常见问题是大括号的放置。

和缩进大小不同,选择或弃用某种放置策略并没有多少技术上的原因,不过首选的方式,就像Kernighan和Ritchie展示给我们的,是把起始大括号放在行尾,而把结束大括号放在行首,所以:if (x is true) {we do y}这适用于所有的非函数语句块(if、switch、for、while、do)。

比如:switch (action) {case KOBJ_ADD:return "add";case KOBJ_REMOVE:return "remove";case KOBJ_CHANGE:return "change";default:return NULL;}不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以:int function(int x){body of function}全世界的异端可能会抱怨这个不一致性是……呃……不一致的,不过所有思维健全的人都知道(a)K&R是_正确的_,并且(b)K&R是正确的。

此外,不管怎样函数都是特殊的(在C语言中,函数是不能嵌套的)。

注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是do语句中的“while”或者if语句中的“else”,像这样:do {body of do-loop} while (condition);和if (x == y) {..} else if (x > y) {...} else {....}理由:K&R。

也请注意这种大括号的放置方式也能使空(或者差不多空的)行的数量最小化,同时不失可读性。

因此,由于你的屏幕上的新行是不可再生资源(想想25行的终端屏幕),你将会有更多的空行来放置注释。

当只有一个单独的语句的时候,不用加不必要的大括号。

if (condition)action();这点不适用于本身为某个条件语句的一个分支的单独语句。

这时需要在两个分支里都使用大括号。

if (condition) {do_this();do_that();} else {otherwise();}3.1:空格Linux内核的空格使用方式(主要)取决于它是用于函数还是关键字。

(大多数)关键字后要加一个空格。

值得注意的例外是sizeof、typeof、alignof和__attribute__,这些关键字某些程度上看起来更像函数(它们在Linux里也常常伴随小括号而使用,尽管在C语言里这样的小括号不是必需的,就像“struct fileinfo info”声明过后的“sizeof info”)。

所以在这些关键字之后放一个空格:if, switch, case, for, do, while但是不要在sizeof、typeof、alignof或者__attribute__这些关键字之后放空格。

例如,s = sizeof(struct file);不要在小括号里的表达式两侧加空格。

这是一个反例:s = sizeof( struct file );当声明指针类型或者返回指针类型的函数时,“*”的首选使用方式是使之靠近变量名或者函数名,而不是靠近类型名。

例子:char *linux_banner;unsigned long long memparse(char *ptr, char **retptr);char *match_strdup(substring_t *s);在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符:= + - < > * / % | & ^ <= >= == != ? :但是一元操作符后不要加空格:& * + - ~ ! sizeof typeof alignof __attribute__ defined后缀自加和自减一元操作符前不加空格:++ --前缀自加和自减一元操作符后不加空格:++ --“.”和“->”结构体成员操作符前后不加空格。

不要在行尾留空白。

有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后你就可以直接在那一行输入代码。

不过假如你最后没有在那一行输入代码,有些编辑器就不会移除已经加入的空白,就像你故意留下一个只有空白的行。

包含行尾空白的行就这样产生了。

当git发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白;不过如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的上下文。

第四章:命名C是一个简朴的语言,你的命名也应该这样。

和Modula-2和Pascal程序员不同,C程序员不使用类似ThisVariableIsATemporaryCounter这样华丽的名字。

C程序员会称那个变量为“tmp”,这样写起来会更容易,而且至少不会令其难于理解。

不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的名字。

称一个全局函数为“foo”是一个难以饶恕的错误。

全局变量(只有当你真正需要它们的时候再用它)需要有一个具描述性的名字,就像全局函数。

如果你有一个可以计算活动用户数量的函数,你应该叫它“count_active_users()”或者类似的名字,你不应该叫它“cntuser()”。

在函数名中包含函数类型(所谓的匈牙利命名法)是脑子出了问题——编译器知道那些类型而且能够检查那些类型,这样做只能把程序员弄糊涂了。

难怪微软总是制造出有问题的程序。

本地变量名应该简短,而且能够表达相关的含义。

如果你有一些随机的整数型的循环计数器,它应该被称为“i”。

叫它“loop_counter”并无益处,如果它没有被误解的可能的话。

类似的,“tmp”可以用来称呼任意类型的临时变量。

如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综合症。

请看第六章(函数)。

第五章:Typedef不要使用类似“vps_t”之类的东西。

对结构体和指针使用typedef是一个错误。

当你在代码里看到:vps_t a;这代表什么意思呢?相反,如果是这样struct virtual_container *a;你就知道“a”是什么了。

很多人认为typedef“能提高可读性”。

实际不是这样的。

它们只在下列情况下有用:(a) 完全不透明的对象(这种情况下要主动使用typedef来隐藏这个对象实际上是什么)。

例如:“pte_t”等不透明对象,你只能用合适的访问函数来访问它们。

注意!不透明性和“访问函数”本身是不好的。

我们使用pte_t等类型的原因在于真的是完全没有任何共用的可访问信息。

(b) 清楚的整数类型,如此,这层抽象就可以帮助消除到底是“int”还是“long”的混淆。

u8/u16/u32是完全没有问题的typedef,不过它们更符合类别(d)而不是这里。

再次注意!要这样做,必须事出有因。

如果某个变量是“unsigned long“,那么没有必要typedef unsigned long myflags_t;不过如果有一个明确的原因,比如它在某种情况下可能会是一个“unsigned int”而在其他情况下可能为“unsigned long”,那么就不要犹豫,请务必使用typedef。

(c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。

相关文档
最新文档