linux内核宏container_of前期准备之gcc扩展关键字typeof

  • typeof基本介绍  

1 typeof(x)

  这是它的使用方法,x可以是数据类型或者表达式。它的作用时期和sizeof类似,就是它是在编译器从高级语言(如C语言)翻译成汇编语言时起作用,这个很重要,稍后会解释。

  当x是数据类型时,它和关键字typedef很相似,只不过typedef是要先定义再使用,而typeof则是可立即使用的,如下:

1 typedef int INT;
2 int main(int argc, const char *argv[])
3 {
4     INT a;
5     typeof(int) b;
6
7     return 0;
8 }

  当x是表达式时:

//变量
int a;
typeof(a)b;

//数组
int c[10];
typeof(c) d;//相当于int d[10];因为c的类型是int *[10]

//函数
int foo(void)
{
    return 0;
}

typeof(foo) c;//foo函数指针类型 int (*)(void)
typeof(foo()) d; //foo函数返回类型 int

  typeof(foo()) d;这句并不会导致函数foo被调用,上面有讲到它的作用时期和sizeof一样,它仅仅是获得x的数据类型,比如对于sizeof:

int a[10];
char len;

len = sizeof(a);

  在编译器将源码由高级语言转到汇编语言时,sizeof关键字就其到了作用。我们甚至可以认为有点类似宏替换(注意发生的阶段不同),相当于是:

int a[10];
char len;

len = 40;

  这一切发生在汇编阶段,typeof也是类似的作用原理,这也就是为什么foo()为什么并没被调用的原因。

  • typeof使用需要注意的问题

  1.typeof构造中的类型名不能包含存储类说明符,如extern或static。不过允许包含类型限定符,如const或volatile。

1 static int a = 5;
2 typeof(a)b; //编译没问题,等于int b;
3 typeof(static int) b; //编译报错
4
5
6 const int a = 2;
7 typeof(a)b = 5;//等同于 const int 5;

  我的个人理解是extern和static的限定只是影响至链接阶段,而const和volatile影响直至执行阶段。好像并不怎么合理,暂时就记录下来吧。

  2.比较容易忽略的一点,通常:

1 int *a,b;    //原意是定义2个int *的变量a,b。初学者容易犯的错误
2
3 //实际要用
4 int *a, *b;
5
6 //但是typeof关键字不是这样的
7 int *a;
8 typeof(a)b,c; //它就是int *b, *c的意思,它不是简单的宏替换,特别要注意
  • 为什么要用typeof,或者说typeof的使用带来了什么好处

  回想我们交换2个变量的方法,最先想到的是利用第三个变量作为中间变量。

1 void swap(int a,int b)
2 {
3     int tmp;
4
5     tmp = b;
6     b = a;
7     a = tmp;
8 }

  如果我要交换的是2个char型变量呢?那岂不是又要写一个函数,太麻烦了。那么强大的typeof来了

#define SWAP(a, b)  {      typeof(a) _t=a;      a=b;      b=_t;}

  一个宏搞定所有基本类型数据交换,甚至是构造类型。妈妈再也不用担心我写到手抽筋了。

参考:

  http://module77.is-programmer.com/posts/22102.html

  http://gcc.gnu.org/onlinedocs/gcc/Typeof.html

时间: 2024-08-10 00:07:43

linux内核宏container_of前期准备之gcc扩展关键字typeof的相关文章

linux内核宏container_of

首先来个简单版本 1 /* given a pointer @ptr to the field @member embedded into type (usually 2 * struct) @type, return pointer to the embedding instance of @type. */ 3 #define container_of(ptr, type, member) 4 ((type *)((char *)(ptr)-(char *)(&((type *)0)->

第01节:Linux 内核中的 C 语言语法扩展

1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来"怪怪的".说它是C语言吧,貌似又跟教材中的写法不太一样:说它不是 C 语言呢,但是这些程序确确实实是在一个 C 文件中.此时,你肯定怀疑你看到的是一个"假的 C 语言"! 比如,下面的宏定义: #define mult_frac(x, numer, denom)( { typeof(x) quo

Linux 内核中的 GCC 特性

转载:http://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/?S_TACT=105AGX52&S_CMP=tec-csdn Linux 内核中的 GCC 特性 了解用于 C 语言的 GCC 扩展 Linux? 内核使用 GNU Compiler Collection (GCC) 套件的几个特殊功能.这些功能包括提供快捷方式和简化以及向编译器提供优化提示等等.了解这些特殊的 GCC 特性,学习如何在 Linux 内核中使用它们. 0 评论:

GCC扩展(转--对看kernel代码有帮助

Linux Kernel的代码,上次就发现一个结构体的定义形式看不懂,后来才知道它用的不是标准的ANSI C,而是GCC的一些扩展.刚好看到<Linux内核修炼之道>中对GCC扩展有所描述,转载一下吧,对看kernel代码有所帮助. 3.5内核代码的特点 Linux内核同时使用C语言和汇编语言实现,C语言编写的代码移植性较好.易于维护,而汇编语言编写的代码相当于针对特定的平台做了优化,速度较快,所以需要在它们之间寻找一定的平衡. 一般而言,在体系结构的底层或对执行时间要求严格的地方,会使用汇编

你为什么看不懂Linux内核驱动源码?

学习嵌入式Linux驱动开发,最核心的技能就是能够编写Linux内核驱动.深入理解Linux内核.而做到这一步的基础,就是你要看得懂Linux内核源码,了解其基本的框架和具体实现,了解其内核API的使用方法,然后才能根据自己的需求写出高质量的内核驱动程序. 说易行难,很多新人.甚至工作1-2年的开发者刚接触Linux内核时,别说写了,看内核代码可能都是一脸懵逼:明明是C语言,但是就是看不懂是什么意思,除了根据函数名.函数参数.函数的返回值以及注释,了解整个函数的基本功能外,一旦分析其细节,你会发

深入浅出实例解析linux内核container_of宏

做一件事情首先应该知道它的目的是什么. container_of的目的:如何通过结构中的某个变量获取结构本身的指针. 总体思路:假想一下,你的结构体中有好几个成员,你如何通过里面的"任一成员"获取整个结构体的首地址呢.container_of的做法就是通过typeof定义一个与"任一成员"同类型的指针变量pvar_a(假设变量名就是pvar_a),并让指针变量pvar_a指向这个"任一成员",然后用 "pvar_a的地址" 减

嵌入式C语言自我修养 04:Linux 内核第一宏:container_of

4.1 typeof 关键字 ANSI C 定义了 sizeof 关键字,用来获取一个变量或数据类型在内存中所占的存储字节数.GNU C 扩展了一个关键字 typeof,用来获取一个变量或表达式的类型.这里使用关键字可能不太合适,因为毕竟 typeof 还没有被写入 C 标准,是 GCC 扩展的一个关键字.为了方便,我们就姑且称之为关键字吧. 通过使用 typeof,我们可以获取一个变量或表达式的类型.所以 typeof 的参数有两种形式:表达式或类型. int i ; typeof(i) j

(十)Linux内核中的常用宏container_of

Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Container_of的定义如下: #define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member)) #define container_of(p, type, member)  ((type *) ((char *)(p) - O

Linux内核中的常用宏container_of

/* linux-2.6.38.8/include/linux/compiler-gcc4.h */ #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) /* linux-2.6.38.8/include/linux/stddef.h */ #undef offsetof #ifdef __compiler_offsetof #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,