TDGG 笔记 GNU C Extension

来源:互联网 发布:php websocket教程 编辑:程序博客网 时间:2024/05/19 00:13

1. Local Declared Labels

申明一个 Label 之后,还需要定义它,然后可以 goto 到指定 Label;

int main(void){       __label__ something; // 声明一个 Label       int foo;       foo=0;       goto something;       {               __label__ something;  // 申明一个 Label,{}作用域内               goto something;               something:            // 定义一个 Label,{}作用域内                       foo++;       }       something:          // 定义一个 Label               return foo;}

如果 Label 定义在宏里面,多次展开有可能造成,Label 的多次定义;可以通过在外面加上({和}),把宏展开中的 Label 定义局限在{}作用域里面;

#define SEARCH(array, target) ({                                __label__ found;                                   \     ...          found:                                             \    value;                                             \})

2. Labels As Values

Label的值是一个常量,类型是void*,可以通过&&得到;

void *ptr;ptr = &&something;goto *ptr; // 还可以通过这种方式跳转// 可以通过 && 求值来初始化一个跳转表static void *jump[] = { &&f, &&g, &&h };goto *array[i];

3. Nested Functions (g++ 不支持)

f(int i, int j){        int i;        // swap 可以访问定义之前的变量i,不能访问之后的变量j;        void swap(int *a, int *b)        {                int tmp = *a;                *a = *b;                *b = tmp;        }        int j; /* more code here */        swap(&i, &j);        save(swap);  // 可以把swap函数地址保存下了,在swap标识符的可见范围外调用它,但不建议使用; }

4.  __builtin_apply_args, __builtin_apply, __builtin_return

例子:

#include <stdio.h>int function1(char * string, int number) {  printf("funtion1: %s\n", string);  return number + 1;}int function2(char * string, int number) {  void* arg_list;  void* return_value;  arg_list = __builtin_apply_args();  return_value =  __builtin_apply( (void*) function1, arg_list, ~CCC    sizeof(char *) + sizeof(int));  __builtin_return(return_value);}int main(int argc, char ** argv) {  printf("returned value: %d\n", function2("hello there", 42));  return 0;}

5. typeof

typeof 语法和 sizeof 一样,但返回的是类型

typeof (expression):如果expression是函数,那么就是函数返回值的类型;

typeof (type):返回类型就是type;

例子:

#define max(a,b)         \
 ({ typeof (a) _a = (a); \
    typeof (b) _b = (b); \

    _a > _b ? _a : _b; })

• typeof (*x) y;: Declares y to be of the type to which x points.
• typeof (*x) y[4];: Declares y to be an array of the values to which x points.
• typeof (typeof (char *)[4]) y;: Declares y as an array of pointers to characters. Clearly, this  
code is more elaborate than the standard C declaration char *y[4];, to which it is equivalent.


6. Zero-Length Arrays

同时参考:GCC: The complete reference p79

Zero-Length Arrary 可以用在结构体的最后,而这个结构体是作为变长对象的数据头的,malloc的时候,可以分配大于结构的大小,之后的数据认为是 Zero-Length Array的;

struct data {        int i;        int j;}struct entry {        int size;        struct data[0];};int e_sz;struct entry *e = (struct entry *) malloc(sizeof (struct entry) + e_sz);e->size = e_sz;

incomplete type:在数组定义的时候,不指定大小;

对于incomplete type数组,在初始化的时候类型自动就补完了;

/* incarray.c */#include <stdio.h>typedef struct {int size;char string[]; // this makes vlen incomlete} vlen;vlen initvlen = { 4, { ‘a’, ‘b’, ‘c’, ‘d’ } }; // complete type vlenint main(int argc,char *argv[]){int i;printf(“sizeof(vlen)=%d\n”,sizeof(vlen)); // 4printf(“sizeof(initvlen)=%d\n”,sizeof(initvlen)); // 4, sizeof() is determined                                                  // during compilingfor(i=0; i<initvlen.size; i++)printf(“%c ”,initvlen.string[i]);printf(“\n”);return(0);}


7. 变长数组

数组的定义,在运行时确定数组长度;

如: char varr[strlen(s1) + strlen(2) + 3]; // strlen() 是运行时确定的

函数定义时,传递变长数组:

void func ( int length, char varr[length] ) { ... }

长度参数也可以在参数列表的后面,但需要先申明,如下:

void func ( int length; char varr[length], int length) { ... };

8. 带变长参数的宏

符合 C99;

#define debug(format, ... ) fprintf(stderr, format, __VA_ARGS__)

省略号代表参数,这些参数会替换__VA_ARGS__;


9.

原创粉丝点击