C语言GNU扩展语法.doc

上传人:枫** 文档编号:546064931 上传时间:2022-12-23 格式:DOC 页数:12 大小:138.01KB
返回 下载 相关 举报
C语言GNU扩展语法.doc_第1页
第1页 / 共12页
C语言GNU扩展语法.doc_第2页
第2页 / 共12页
C语言GNU扩展语法.doc_第3页
第3页 / 共12页
C语言GNU扩展语法.doc_第4页
第4页 / 共12页
C语言GNU扩展语法.doc_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《C语言GNU扩展语法.doc》由会员分享,可在线阅读,更多相关《C语言GNU扩展语法.doc(12页珍藏版)》请在金锄头文库上搜索。

1、GNU C 9条扩展语法GNC CC是一个功能非常强大的跨平台C编译器,它对标准C语言进行了一系列扩展,以增强标准C的功能,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。本文把支持GNU扩展的C语言称为GNU C。Linux内核代码使用了大量的GNU C扩展,以至于能够编译Linux内核的唯一编译器是GNU CC,以前甚至出现过编译Linux内核要使用特殊的GNU CC版本的情况。本文是对Linux内核使用的GNU C扩展的一个汇总,希望当你读内核源码遇到不理解的语法和语义时,能从本文找到一个初步的解答,更详细的信息可以查看gcc.info。文中的例子取自 Linux 2.

2、4.18。1、 零长度和变量长度数组GNU C允许使用零长度数组,在定义变长对象的头结构时,这个特性非常有用。例如:/include/linux/minix_fs.hstruct minix_dir_entry _u16 inode;char name0;结构的最后一个元素定义为零长度数组,它不占结构的空间。在标准C中则需要定义数组长度为1,分配时计算对象大小比较复杂。GNU C 允许使用一个变量定义数组的长度,比如:int n=0;scanf(%d,&n);int arrayn;2、 case范围GNU C允许在一个case标号中指定一个连续范围的值,例如:/arch/i386/kernel

3、/irq.ccase 0 . 9: c -= 0; break;case a . f: c -= a-10; break;case A . F: c -= A-10; break;3、语句表达式GNU C把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本只能在复合语句中使用。例如:/include/linux/kernel.h#define min_t(type,x,y) ( type _x = (x); type _y = (y); _x window_clamp,tcp_full_space(sk);复

4、合语句的最后一个语句应该是一个表达式,它的值将成为这个语句表达式的值。这里定义了一个安全的求最小值的宏,在标准C中,通常定义为:#define min(x,y) (x) (y) ? (x) : (y)这个定义计算x和y分别两次,当参数有副作用时,将产生不正确的结果,使用语句表达式只计算参数一次,避免了可能的错误。语句表达式通常用于宏定义。4、typeof 关键字使用前一节定义的宏需要知道参数的类型,利用typeof可以定义更通用的宏,不必事先知道参数的类型,例如:/include/linux/kernel.h#define min(x,y) ( /const typeof(x) _x = (x

5、); /const typeof(y) _y = (y); /(void) (&_x = &_y); /_x _y ? _x : _y; )这里typeof(x)表示x的值类型,第3行定义了一个与 x 类型相同的局部变量 _x 并初使化为 x,注意第5行的作用是检查参数x和y的类型是否相同。typeof 可以用在任何类型可以使用的地方,通常用于宏定义。5、可变参数宏在GNU C中,宏可以接受可变数目的参数,就象函数一样,例如:/include/linux/kernel.h#define pr_debug(fmt,arg.) printk(KERN_DEBUG fmt,#arg)这里arg表示其

6、余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成arg的值,在宏扩展时替换arg,例如:pr_debug(%s:%d,filename,line)扩展为printk( %s:%d, filename, line)使用#的原因是处理arg不匹配任何参数的情况,这时arg的值为空,GNU C预处理器在这种特殊情况下,丢弃#之前的逗号,这样pr_debug(success!/n)扩展为 printk( success!/n)注意最后没有逗号。6、标号元素标准C要求数组或结构变量的初使化值必须以固定的顺序出现,在GNU C中,通过指定索引或结构域名,允许初始化值以任意顺序出现。指定数组索引的

7、方法是在初始化值前写 INDEX =,要指定一个范围使用FIRST . LAST =的形式,例如:/arch/i386/kernel/irq.cstatic unsigned long irq_affinity NR_IRQS = 0 . NR_IRQS-1= 0UL ;将数组的所有元素初使化为0UL,这可以看做是一种简写形式。要指定结构元素,在元素值前写FIELDNAME:,例如:/fs/ext2/file.cstruct file_operations ext2_file_operations = llseek: generic_file_llseek,read: generic_file

8、_read,write: generic_file_write,ioctl: ext2_ioctl,mmap: generic_file_mmap,open: generic_file_open,release: ext2_release_file,fsync: ext2_sync_file,;将结构ext2_file_operations的元素llseek初始化为generic_file_llseek,元素read初始化为genenric_file_read,依次类推。我觉得这是GNU C扩展中最好的特性之一,当结构的定义变化以至元素的偏移改变时,这种初始化方法仍然保证已知元素的正确性。对于

9、未出现在初始化中的元素,其初值为 0。标准C要求数组或结构体的初始化值必须以固定的顺序出现,在GNU C中,通过指定索引或结构体成员名,允许初始化以任意顺序出现。unsigned char dataMAX =0=10,10=100,;struct file_operations ext2_file_operations=open:ext2_open,close:ext2_close,;在linux 2.6中推荐如下方式:struct file_operations ext2_file_operations=.read=ext2_read,.write=ext2_write,;7、当前函数名GN

10、U C中预定义两个标志符保存当前函数的名字,_FUNCTION_保存函数在源码中的名字,_PRETTY_FUNCTION_保存带语言特色的名字。在C函数中这两个名字是相同的。在C+函数中,_PRETTY_FUNCTION_包括函数返回类型等额外信息,Linux内核只使用了_FUNCTION_。/fs/ext2/super.cvoid ext2_update_dynamic_rev(struct super_block *sb)struct ext2_super_block *es = EXT2_SB(sb)-s_es;if (le32_to_cpu(es-s_rev_level) EXT2_G

11、OOD_OLD_REV) return;ext2_warning(sb, _FUNCTION_, updating to rev %d because of new feature flag, running e2fsck is recommended, EXT2_DYNAMIC_REV);这里_FUNCTION_将被替换为函数名ext2_update_dynamic_rev。虽然_FUNCTION_ 看起来类似于标准C中的_FILE_,但实际上_FUNCTION_是被编译器替换的,不象 _FILE_被预处理器替换。在C99中支持_func_宏,因此建议使用_func_替代_FUNCTION_

12、8、特殊属性声明GNU C允许声明函数、变量和类型的特殊属性,以便进行手工的代码优化和定制代码检查的方法。要指定一个声明属性,只需要在声明后添加_attribute_(ATTRIBUTE)。其中ATTRIBUTE为属性说明,如果存在多个属性,则以逗号分隔。GNU C 支持noreturn、format、section、aligned、packed等十个属性。这里介绍最常用的:noreturn属性用于函数,表示该函数从不返回。这可以让编译器生成稍微优化的代码,最重要的是可以消除不必要的警告信息比如未初使化的变量。例如:/include/linux/kernel.h#define ATTRIB_N

13、ORET _attribute_(noreturn) .asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)属性用于函数,表示该函数使用printf, scanf或strftime风格的参数,使用这类函数最容易犯的错误是格式串与参数不匹配,指定 format 属性可以让编译器根据格式串检查参数类型。例如:/include/linux/kernel.h?asmlinkage int printk(const char * f

14、mt, .) _attribute_ (format (printf, 1, 2);表示第一个参数是格式串,从第二个参数起根据格式串检查参数。unused属性用于函数和变量,表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。section (section-name)属性用于函数和变量,通常编译器将函数放在.text区,变量放在.data区或.bss区,使用section属性,可以让编译器将函数或变量放在指定的节中。例如:/include/linux/init.h#define _init _attribute_ (_section_ (.text.init)#define _exit _attribute_ (unused,_section_(.text.exit)#define _initdata _attribute_ (_section_ (.data.init)#define _exitdata _attribute_ (

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号