常用GNU C技巧
GNU C对ANSI C进行了扩展,所以GCC有一些扩展的新特性
(1)语句表达式
括号里的复合语句可以看作一个表达式,并可以使用循环和局部变量等。通常用在宏定义中,可以让宏定义更加安全。
#define max(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b;})
(2) typeof
可用来获取类型来构造新的类型
typeof (*x) y; //声明y是x指针指向的类型
(3)零长数组
允许使用变长数组
<mm/percpu.c>
struct pcpu_chunk{
struct list_head list;
unsigned long populated[]; /*变长数组*/
}
populated被定义为0长度数组,不占结构体空间。
(4)case 范围
case支持范围作为标签
case low ... high:
case 'A' ... 'Z':
case 1 ... 3:
"…"两边有空格。
(5) 标号元素
- 在标准C里,数组或者结构变量的初始化值必须以固定的顺序出现,而在GCC中,通过制定索引或者结构域名,则允许初始化值以任意顺序出现。
对于结构体初始化,比如:
struct person Bill = {
.name = “Bill Gates”;
.age = 50;
.wealth’s world ranking = 1;
};
(6)可变参数宏
宏可以接收可变数目的参数,主要运用再输出函数里
#define pr_debug(fmt,arg...) \
printk(fmt,##arg)
使用“##”是为了处理 arg 不代表任何参数的情况,这时候,前面的逗号就变得多余了。
(7)函数属性
- GNU C 允许声明函数、变量和类型的特殊属性,以便手动优化代码和定制代码检查的方法。
- 格式为
__attribute__((attribute_list))
(8)内建函数
- GNU C 提供了大量内建函数,其中大部分是标准 C 库函数的 GNU C 编译器内建版本,以“builtin”作为函数名前缀。
(9)asmlinkage
- 对于x86结构,函数参数和局部变量被一起分配到函数的局部堆栈中
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
attribute((regparm(0))):告诉编译器该函数不需要通过任何寄存器来传递参数,只通过堆栈来传递。
(10)UL
UL强制把int类型定义为unsigned long类型,防止溢出
1UL
表示无符号长整形数字1.