Menu

C的语法扩展,语法扩展



图片 1

图片 1

要研究LINUX内核,C语言是基础中的基础,但是LINUX并不是完全的标准C,而是对标准C做了很多扩展,这些扩展特性对于我们分析内核有着很重要的作用,下面做些总结性的工作。

要研究LINUX内核,C语言是基础中的基础,但是LINUX并不是完全的标准C,而是对标准C做了很多扩展,这些扩展特性对于我们分析内核有着很重要的作用,下面做些总结性的工作。

  • GCC允许你在任何内嵌代码块中声明局部标签,所谓的局部标签跟普通的标签用法一样(用在goto语句或者被获取地址),只不过你只能在声明它的代码块中使用。局部标签的声明如下:

1 语句表达式

  • GNUC把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本只能在复合语句中使用。

  • 复合语句的最后一个语句应该是一个表达式,它的值将成为这个语句表达式的值。

  • 例如:该语句就是一个合法的复合语句,它的值为foo()。

({\ int y=foo();\ int z; \ if\ z=y;\ else\ z=-y;\ z;\})
  • 这种特性在宏定义中尤为安全。(因为他们对操作数只进行一次赋值)。这里定义了一个安全的求最小值的宏,在标准C中,通常定义为:

#define max>:
  • 在这种定义下,a和b将进行两次运算,如果他们有副作用的话将会得到错误的结果。在GNU
    C中,如果你知道操作数的类型,你可以这样来定义这个宏:

#define maxint ({int_a=; _a>_b?_a:_b;})
  • 在嵌入式语句中,不允许使用常量表达式,如枚举常量、位域常量和初始化静态变量。当然,如果你不知道参数的具体类型,你也可以使用typeof或__auto_type运算符。

===========我是华丽的分割线===========

更多知识:点击关注专题:嵌入式Linux&ARM

或浏览器打开:

或扫描二维码:

图片 3

__label__ label; 

或者

__label__ label1, label1, … ;
  • 局部标签声明只是定义了标签的名字,但是并没有定义标签本身,它本身必须像普通标签那样在语句内嵌表达式内部使用局部标签。
  • 另外要注意的是,局部标签的声明必须在代码块的起始位置(即位于任何其他声明和语句之前)。
  • 在复杂的宏定义中,局部标签显得尤为有用。如果一个宏包含有内嵌循环,goto语句可以方便地跳出它们。然而,拥有整个函数作用域的普通标签在这里不能被使用,因为该宏可能会在一个函数中被展开若干次,那样的话同样的一个标签就会被重复定义。局部标签就是用来避免这种情况的。例如:

#define SEARCH(value, array, target) do { __label__ found; typeof  _SEARCH_target = ; typeof  *_SEARCH_array = ;int i, j; int value; for (i = 0; i < max; i++) for (j = 0; j < max; j++) if (_SEARCH_array[j] == _SEARCH_target) {  = i; goto found; }  = -1; found:;} while 

当然,也可以用语句表达式改写这个宏定义:

#define SEARCH(value, array, target) ({ __label__ found; typeof  _SEARCH_target = ; typeof  *_SEARCH_array = ;int i, j; int value; for (i = 0; i < max; i++) for (j = 0; j < max; j++) if (_SEARCH_array[j] == _SEARCH_target) {  = i; goto found; }  = -1; found: value;})
  • 局部标签在内嵌函数中也是可见的。

注意:我们用语句表达式的时候,在最后的found局部标签后面有个语句
value; 而在do …
while循环中并无出现,原因是语句表达式的值取决于最后的表达式,而do …
while 循环中的found局部标签仅仅用来跳出循环

===========我是华丽的分割线===========

更多知识:点击关注专题:嵌入式Linux&ARM

或浏览器打开:

或扫描二维码:

图片 3

标签:,

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图