GNU C和标准C的区别

GNU C是什么?GNU C建立在自由软件基金会的编程许可证的基础上 , 因此可以自由发布 。GNU C对标准C进行进一步扩展 , 以增强标准C的功能 。
特别是嵌入式软件开发过程中 , 经常会遇到很多GNU C的语法 , 以为是C语言没学过关 , 其实很多都不是标准C语言中的语法 。哈哈!
 
扩展差异1、零长度数组
GNU C 允许使用零长度数组 , 在定义变长对象的头结构时 , 这个特性非常有用 。例如:
struct minix_dir_entry {    __u16 inode;    char name[0];};结构的最后一个元素定义为零长度数组 , 它不占结构的空间 。在标准 C 中则需要定义数组长度为 1 , 分配时计算对象大小比较复杂 。
 
2、case范围
GNU C 允许在一个 case 标号中指定一个连续范围的值 , 例如:
case '0' ... '9': c -= '0'; break; case 'a' ... 'f': c -= 'a'-10; break; case 'A' ... 'F': c -= 'A'-10; break;其中case '0' ... '9': 相当于 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
3、语句表达式
GNU C 把包含在括号中的复合语句看做是一个表达式 , 称为语句表达式 , 它可以出现在任何允许表达式的地方 , 你可以在语句表达式中使用循环、局部变量等 , 原本只能在复合语句中使用 。例如:
#define min_t(type,x,y)  ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })复合语句的最后一个语句应该是一个表达式 , 它的值将成为这个语句表达式的值 。这里定义了一个安全的求最小值的宏 , 在标准 C 中 , 通常定义为:
#define min(x,y) ((x) < (y) ? (x) : (y))这个定义计算 x 和 y 分别两次 , 当参数有副作用时(比如出现参数自增或自减语句时) , 将产生不正确的结果 , 使用语句表达式只计算参数一次 , 避免了可能的错误 。语句表达式通常用于宏定义 。
4、typeof关键字
使用前一节定义的宏需要知道参数的类型 , 利用 typeof 可以定义更通用的宏 , 不必事先知道参数的类型 , 例如:
#define min(x,y) ({  const typeof(x) _x = (x);       const typeof(y) _y = (y);       (void) (&_x == &_y);           _x < _y ? _x : _y; })这里 typeof(x) 表示 x 的值类型 ,  const typeof(x) _x = (x); 中定义了一个与 x 类型相同的局部变量 _x 并初使化为 x ,  (void) (&_x == &_y); 的作用是检查参数 x 和 y 的类型是否相同 。typeof 可以用在任何类型可以使用的地方 , 通常用于宏定义 。
5、可变参数的宏
在 GNU C 中 , 宏可以接受可变数目的参数 , 就象函数一样 , 例如:
#define pr_debug(fmt,arg...) printk(fmt,##arg)这里 arg 表示其余的参数 , 可以是零个或多个 , 这些参数以及参数之间的逗号构成 arg 的值 , 在宏扩展时替换 arg , 例如:
pr_debug("%s:%d",filename,line)会被扩展为
printk("%s:%d", filename, line)使用 ## 的原因是处理 arg 不匹配任何参数的情况 , 这时 arg 的值为空 , GNU C 预处理器在这种特殊情况下 , 丢弃 ## 之前的逗号 , 这样
pr_debug("success!n")会被扩展为
printk("success!n")而不是printk("success!n" , )
注意最后的逗号 。
6、标号元素
标准 C 要求数组或结构变量的初使化值必须以固定的顺序出现 , 在 GNU C 中 , 通过指定索引或结构域名 , 允许初始化值以任意顺序出现 。指定数组索引的方法是在初始化值前写 '[INDEX] =' , 要指定一个范围使用 '[FIRST ... LAST] =' 的形式 , 例如:
static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };将数组的所有元素初使化为 ~0UL , 这可以看做是一种简写形式 。
要指定结构元素 , 在元素值前写 'FIELDNAME:' , 例如:
struct file_operations ext2_file_operations = {      llseek:       generic_file_llseek,      read:           generic_file_read,      write:       generic_file_write,      ioctl:       ext2_ioctl,      mmap:           generic_file_mmap,      open:           generic_file_open,      release:        ext2_release_file,      fsync:       ext2_sync_file, };


推荐阅读