GNU C 语法扩展(2)
原创
©著作权归作者所有:来自51CTO博客作者leon_george的原创作品,请联系作者获取转载授权,否则将追究法律责任
要研究LINUX内核,C语言是基础中的基础,但是LINUX并不是完全的标准C,而是对标准C做了很多扩展,这些扩展特性对于我们分析内核有着很重要的作用,下面做些总结性的工作。
2 局部标签
- GCC允许你在任何内嵌代码块中声明局部标签,所谓的局部标签跟普通的标签用法一样(用在goto语句或者被获取地址),只不过你只能在声明它的代码块中使用。局部标签的声明如下:
或者
__label__ label1, label1, … ;
- 局部标签声明只是定义了标签的名字,但是并没有定义标签本身,它本身必须像普通标签那样在语句内嵌表达式内部使用局部标签。
- 另外要注意的是,局部标签的声明必须在代码块的起始位置(即位于任何其他声明和语句之前)。
- 在复杂的宏定义中,局部标签显得尤为有用。如果一个宏包含有内嵌循环,goto语句可以方便地跳出它们。然而,拥有整个函数作用域的普通标签在这里不能被使用,因为该宏可能会在一个函数中被展开若干次,那样的话同样的一个标签就会被重复定义。局部标签就是用来避免这种情况的。例如:
#define SEARCH(value, array, target)
do {
__label__ found;
typeof (target) _SEARCH_target = (target);
typeof (*(array)) *_SEARCH_array = (array);int i, j; int value;
for (i = 0; i < max; i++)
for (j = 0; j < max; j++)
if (_SEARCH_array[j] == _SEARCH_target)
{ (value) = i; goto found; }
(value) = -1;
found:;
} while (0)
当然,也可以用语句表达式改写这个宏定义:
#define SEARCH(value, array, target)
({ __label__ found;
typeof (target) _SEARCH_target = (target);
typeof (*(array)) *_SEARCH_array = (array);int i, j; int value;
for (i = 0; i < max; i++)
for (j = 0; j < max; j++)
if (_SEARCH_array[j] == _SEARCH_target)
{ (value) = i; goto found; }
(value) = -1;
found:
value;
})
注意:我们用语句表达式的时候,在最后的found局部标签后面有个语句 value; 而在do ... while循环中并无出现,原因是语句表达式的值取决于最后的表达式,而do ... while 循环中的found局部标签仅仅用来跳出循环