[转] GCC扩展(2)
■ 内部函数
gcc 扩充一个类似 java 内部类的功能,一个函数内部可以嵌套定义一个子函数。
子函数不能被外部访问,只能被嵌套它的函数访问。
void hi(char *s)
{
auto void say_hi(char *s);
char *me = "I'm a inner function";
say_hi(s);
void say_hi(char *s)
{
printf("Hi, %s: %s\n", s, me);
}
}
int main()
{
hi("mik"); // OK
say_hi("mik"); // Error
return 0;
}
说明:1、内部函数不能被 extern 声明。
2、inner functon 原型要声明为 auto
3、像 local variable 一样,不要返回 inner function 地址 给 调用函数。
4、像 local variable 一样的方式可以访问 inner function
■ 标识符支持 $ 符号
例如: char *p$ = "mik"; 是正确的。
■ 支持获得 lable 地址
通过 && 获得 label 地址。
int main()
{
void *ptr = 0;
ptr = && label2;
goto *ptr;
label1:
printf("this is a label1\n");
return 0;
label2:
printf("this is a label2\n");
return 0;
}
类似地:
void *ptr[] = { &&label1, &&label2, &&label3 };
goto *ptr[i];
■ 关于左值 (lvalue)
在一个 = 表达式里,= 左边被叫作左值。 左值的一个明显特征是具有地址属性。
一般表现为一个变量。
左值的表现:
(1) a = 5; // a 是一个 lvalue, 5 被存放在 a 的地方。
(2) ptr = &a; // a 虽然出现在 = 右边,但它依然是个 lvalue 概念。
(3) 复合语句中:
(fn(), a) = 10; // a 是个 lvalue;
(4) 同样复合语句中:
ptr = &(fn(), a); // a 依然是个 lvalue
(5) 条件表达式中:
(a > b ? a : b ) = 10; // a,b 都可能是 lvalue
(6) cast 表达式中:
char * ptr;
(int)ptr = 0x0804020; // cast 情况下的 lvalue
■ gcc 充许对 void * 指针进行运算。
void *p = 0;
p++;
指针 p 会加 1, p++ 相当于 p = p + 1;
具体类型的指针加1,会在加上具体类型 size 值。
例1: int *p = &i;
p++; // 在 &i 的基础上加 4
例2:
void *p = 0;
printf("%d\n", ({void *tp = p; ++p - tp;}));
结果是:1 说明对 void * 指针 ++ 或 -- 是物理上加1或减1
■ 对 switch / case 的扩充
ISO C :
case 1:
case 2:
case 3:
case 4:
....
case 10: break
gcc:
case 1...10:
■ typeof 操作符
typeof(int) i; // 等同于 int i;
typeof(i) j; // 等同于 int j;
typeof(int *) p; // 等同于 int *p;
typeof 的特殊用法:
一个通用的 swap 宏:
#define swap(a,b) \
( { typeof(*a) t = *a; \
*a = *b; \
*b = t; \
} )
int main()
{
char a = 'a';
char b = 'b';
swap(&a, &b); // 结果是 a = 'b', b = 'a'
int i = 5;
int j = 10;
swap(&i, &j); // 结果是 i = 10, j = 5
return 0;
}