GNU C 允许使用零长度数组,在定义变长对象的头结构时,这个特性非常有用。例如:
struct var _ data { int len; char data[0]; };
struct var _ data s; ... for (i = 0; i < s.len; i++) { printf("%02x", s.data[i]); }
switch (ch) { case '0'... '9': c -= '0'; break; case 'a'... 'f': c -= 'a' - 10; break; case 'A'... 'F': c -= 'A' - 10; break; }
case '0': case '1': case '2': case '3': case '4':case'5': case '6': case '7': case '8': case '9':
#define min _ t(type,x,y) \ ({ type _ _ x = (x); type _ _ y = (y); _ _ x < _ _ y ? _ _ x: _ _ y; }) int ia, ib, mini; float fa, fb, minf; mini = min _ t(int, ia, ib); minf = min _ t(float, fa, fb);
extern int foo(); typeof(foo()) var;
typeof(int *) a,b;以上语句等价于:
int a,b;
注意,使用typeof构造的类型名不能包含存储类说明符,如extern或static。不过允许包含类型限定符,如const或volatile。例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;typeof构造的主要应用是用在宏定义中。可以使用typeof关键字来引用宏参数的类型。因此,在没有将类型名明确指定为宏实参的情况下,构造带有所需类型的对象是可能的。
#define SWAP(a,b) {\ typeof(a) _t=a;\ a=b;\ b=_t;}
int printf( const char *format [, argument]... );
而在GNU C中,宏也可以接受可变数目的参数,例如:
#define pr _ debug(fmt,arg...) \ printk(fmt,##arg)这里arg表示其余的参数可以是零个或多个,这些参数以及参数之间的逗号构成arg 的值,在宏扩展时替换arg,例如下列代码:
pr _ debug("%s:%d",filename,line)会被扩展为:
printk("%s:%d", filename, line)使用“##”的原因是处理arg不代表任何参数的情况,这时候前面的逗号就变得多余了。使用“##”之后,GNU C预处理器会丢弃前面的逗号,这时
pr _ debug("success!\n")
会被正确地扩展为:
printk("success!\n")而不是:
printk("success!\n",)
unsigned char data[MAX] = { [0 ... MAX-1] = 0 };下面的代码借助结构体成员名初始化结构体:
struct file _ operations ext2 _file_operations = { llseek: generic _ file _ llseek, read: generic _ file _ read, write: generic _ file _ write, ioctl: ext2 _ ioctl, mmap: generic _ file _ mmap, open: generic _ file _ open, release: ext2 _ release _ file, fsync: ext2 _ sync _ file, };但是,Linux 2.6 推荐类似的代码应该尽量采用标准 C 的方式,如下所示:
struct file _ operations ext2_file_operations = { .llseek = generic _ file _ llseek, .read = generic _ file _ read, .write = generic _ file _ write, .aio _ read = generic _ file _ aio _ read, .aio _ write = generic _ file _ aio _ write, .ioctl = ext2 _ ioctl, .mmap = generic _ file _ mmap, .open = generic _ file _ open, .release = ext2 _ release _ file, .fsync = ext2 _ sync _ file, .readv = generic _ file _ readv, .writev = generic _ file _ writev, .sendfile = generic _ file _ sendfile, };
void example() { printf("This is function:%s", _ _ FUNCTION _ _ ); }
# define ATTRIB _ NORET _ _ attribute _ _ ((noreturn)) .... asmlinkage NORET _ TYPE void do _ exit(long error _ code) ATTRIB _ NORET;format属性也用于函数,表示该函数使用printf、scanf 或strftime风格的参数,指定 format 属性可以让编译器根据格式串检查参数类型。例如:
asmlinkage int printk(const char * fmt, ...) _ _ attribute _ _ ((format (printf, 1, 2)));
struct example _ struct { char a; int b; long c; } _ _ attribute _ _ ((aligned(4)));
struct example _ struct { char a; int b; long c _ _ attribute _ _ ((packed)); };
#define test _ bit(nr,addr) \ ( _ _ builtin _ constant _ p(nr) ? \ constant _ test _ bit((nr),(addr)) : \ variable _ test _ bit((nr),(addr)))