Linux 内核C语言的特点.ppt
文本预览下载声明
GNU对C语言的扩展 Linux内核程序的特点 语句表达式 GNU C 把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等。 include/linux/kernel.h159: #define min_t(type,x,y) \160: ({ type __x = (x); type __y = (y); __x __y ? __x: __y; }) 这里定义了一个安全的求最小值的宏 语句表达式 在标准 C 中,通常定义为: #define min(x,y) ((x) (y) ? (x) : (y)) 这个定义计算 x 和 y 分别两次,当参数有副作用时,将产生不正确的结果 使用语句表达式只计算参数一次,避免了可能的错误。 语句表达式通常用于宏定义。 Typeof 使用前一节定义的宏需要知道参数的类型,利用 typeof 可以定义更通用的宏,不必事先知道参数的类型 include/linux/kernel.h141: #define min(x,y) ({ \142: const typeof(x) _x = (x); \143: const typeof(y) _y = (y); \144: (void) (_x == _y); \145: _x _y ? _x : _y; }) Typeof (void) (_x == _y)这句话本身都执行程序来讲完全是一句废话 它的作用在于,本身我们无法做这样的操作typeof(_x)==typeof(_y),所以故意判断他们2个的地址指针是否相等,显然是不可能相等, 但是如果_x和_y的类型不一样,其指针类型也会不一样,2个不一样的指针类型进行比较操作,会抛出一个编译警告。 比如:char *p; int *q; 然后p==q;,这个判断因为一个是char*一个是int*,会在编译时产生一个warning 零长度数组 GNU C 允许使用零长度数组 在定义变长对象的头结构时,这个特性非常有用。结构的最后一个元素定义为零长度数组,它不占结构的空间。 在标准 C 中则需要定义数组长度为 1,分配时计算对象大小比较复杂。 struct { int length; char content[0]; }; 零长度数组 例子:/usr/include/linux/if_pppox.h struct pppoe_tag { ??? __u16 tag_type; ??? __u16 tag_len; ??? char tag_data[0]; } __attribute ((packed)); 零长度数组 使用起来非常方便,创建时,malloc一段结构体大小加上可变长数据长度的空间给它,可变长部分可按数组的方式访问 struct pppoe_tag *sample_tag; __u16 sample_tag_len = 10; sample_tag = (struct pppoe_tag *)malloc(sizeof(struct pppoe_tag)+sizeof(char)*sample_tag_len); sample_tag-tag_type = 0xffff; sample_tag-tag_len = sample_tag_len; sample_tag-tag_data[0]=.... ? ... 零长度数组 释放时,直接把整个结构体free掉就可以了 free(sample_tag) 可变参数宏 在 GNU C 中,宏可以接受可变数目的参数,就象函数一样 例如 include/linux/kernel.h110: #define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt,##arg) arg 表示其余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成 arg 的值,在宏扩展时替换 arg 可变参数宏 pr_debug(%s:%d,filename,line)扩展为 printk(7 %s:%d, filename, line) pr_debug(success!\n“)扩展为 printk(7 success!\n) 标号元素 标准 C 要求数组或结构变量的初使化值必须以固定的顺序出现 在 GNU C 中,通过指定索引或结构域名,允许初始化值以任意顺序出现。 指定数组索引的方法是在初始化值前写 [INDEX] =,要指定一个范围使用 [FIRST ... LAST] = 的形式 标号元素 fs/ext2/file.c41: struct file_operations ext2_fil
显示全部