在朋友的博客上看到这样的
C
语言初始化方式:
int
arr[10] = { [5] = 7 }; // a[5] = 7;
以前没有用过也不知道有这样的写法。在网上找了一下这方面的资料,最后在
http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/C-Extensions.html
找到了答案。以下所有内容都来自这个网址。
上面的那行 C 语言初始化语法叫做 Designated Initializers ,是 GNU C 编译器对 ISO C 标准的扩展。在 gcc 编译器中使用 -pedantic 选项,就可以让 gcc 找出代码中所有 GNU C 的扩展语法并输出警告信息。如果要使用条件编译来检测这些扩展特性是否可用,只需要检测宏 __GNUC__ 是否被定义。
这些扩展特性中的一部分特性已经被 C99 标准承认。以下是对上述网址处的内容的笔记:
({ int y = foo (); int z;
if (y > 0) z = y;
else z = - y;
z; })
这段代码展示了这种语法的形式。复合语句中的最后一条语句 ( 或者表达式 ) 的值代表了整个这个语法结构的值 ( 和逗号表达式一样 ) ,在上面这段代码来说,它的值就是最后 z 的值。
这种技术在宏定义中特别有用,它引入了局部变量,消去了宏定义中变量可能被多次求值的问题。例如,可以这样定义求两个整数的最大值的宏:
#define maxint(a,b) /
({ int _a = (a), _b = (b); _a > _b ? _a : _b; })
局部标号的声明必须出现在表达式语句的最开始的地方,也就是紧接着 ({ 的地方。这种局部标号的技术为上面的表达式语句 (statement expression) 技术带来了很大的方便。因为通常表达式语句出现在宏定义中,宏定义可能会有嵌套的循环,在这种情况下局部标号可以方便地跳出循环体。因为它的生存期仅在包含它的表达式语句中,所以含有局部标号的宏在同一个函数中多次展开不会引起标号的重复定义。下面是这种技术的应用体现,其中还有 typeof 语法,也属于扩展特性,后面会有介绍:
#define SEARCH(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++) /
上面的那行 C 语言初始化语法叫做 Designated Initializers ,是 GNU C 编译器对 ISO C 标准的扩展。在 gcc 编译器中使用 -pedantic 选项,就可以让 gcc 找出代码中所有 GNU C 的扩展语法并输出警告信息。如果要使用条件编译来检测这些扩展特性是否可用,只需要检测宏 __GNUC__ 是否被定义。
这些扩展特性中的一部分特性已经被 C99 标准承认。以下是对上述网址处的内容的笔记:
Statements and Declarations in Expressions
使用圆括号括起来的复合语句 ( 复合语句是用一对花括号括起来来的语句,所以这种语法的形式就是一对花括号外面再括上一对圆括号,具体例子见下面 ) 地位上相当于一个普通表达式 ,可以在其中使用循环、条件分支以及局部变量。下面是一个例子:({ int y = foo (); int z;
if (y > 0) z = y;
else z = - y;
z; })
这段代码展示了这种语法的形式。复合语句中的最后一条语句 ( 或者表达式 ) 的值代表了整个这个语法结构的值 ( 和逗号表达式一样 ) ,在上面这段代码来说,它的值就是最后 z 的值。
这种技术在宏定义中特别有用,它引入了局部变量,消去了宏定义中变量可能被多次求值的问题。例如,可以这样定义求两个整数的最大值的宏:
#define maxint(a,b) /
({ int _a = (a), _b = (b); _a > _b ? _a : _b; })
Locally Declared Labels
每一条表达式语句 (statement expression) 都定义了一个作用域,在这个作用域内可以声明一个或多个局部标号。声明标号的语法形式为: __label__ label; 或者声明多个标号: __label__ label1, label2, ...;局部标号的声明必须出现在表达式语句的最开始的地方,也就是紧接着 ({ 的地方。这种局部标号的技术为上面的表达式语句 (statement expression) 技术带来了很大的方便。因为通常表达式语句出现在宏定义中,宏定义可能会有嵌套的循环,在这种情况下局部标号可以方便地跳出循环体。因为它的生存期仅在包含它的表达式语句中,所以含有局部标号的宏在同一个函数中多次展开不会引起标号的重复定义。下面是这种技术的应用体现,其中还有 typeof 语法,也属于扩展特性,后面会有介绍:
#define SEARCH(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++) /