前言:计算机语言是编译器和程序员交流的依据和规范,GNU C是GCC特有的功能,在Linux内核中被广泛应用。
帮助文档:http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
在GNU C中,可以在结构体中声明某个联合体(或结构体)而不用指出它的名字,如此之后就可以像使用结构体成员一样直接使用其中联合体(或结构体)的成员。
举例,如test.c:
#include <stdio.h>
struct test_struct {
char *name;
union {
char gender;
int id;
};
int num;
};
int main(void)
{
struct test_struct test_struct = {"tanglinux", 'F', 28 };
printf("test_struct.gender = %c, test_struct.id = %d\n",
test_struct.gender, test_struct.id);
return 0;
}
例子输出结果:
test_struct.gender = F, test_struct.id = 70
例子中的第17行,结构体变量test_struct直接使用联合体中的成员gender或id。
GCC默认情况下可以使用GNU C的各种扩展功能,如果上例使用C99标准编译的话,会产生以下的错误:
$ gcc -std=c99 test.c -o test
test.c:8:6: warning: declaration does not declare anything
test.c: In function 'main':
test.c:14:12: warning: excess elements in struct initializer
test.c:14:12: warning: (near initialization for 'test_struct')
test.c:17:17: error: 'struct test_struct' has no member named 'gender'
test.c:17:37: error: 'struct test_struct' has no member named 'id'
修改上例,使其符合C99标准,如test01.c:
#include <stdio.h>
union test_union {
char gender;
int id;
};
struct test_struct {
char *name;
union test_union test_union;
int num;
};
int main(void)
{
struct test_struct test_struct = {"tanglinux", 'F', 28 };
printf("test_struct.test_union.gender = %c, test_struct.test_union.id = %d\n",
test_struct.test_union.gender, test_struct.test_union.id);
return 0;
}
例子输出结果:
$ gcc -std=c99 test01.c -o test01
test_struct.test_union.gender = F, test_struct.test_union.id = 70
在Linux内核中常用匿名联合(或结构体),如在linux-2.6.38.8/fs/sysfs/sysfs.h文件中struct sysfs_dirent结构体的定义:
struct sysfs_dirent {
atomic_t s_count;
atomic_t s_active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
struct sysfs_dirent *s_parent;
struct sysfs_dirent *s_sibling;
const char *s_name;
const void *s_ns; /* namespace tag */
union {
struct sysfs_elem_dir s_dir;
struct sysfs_elem_symlink s_symlink;
struct sysfs_elem_attr s_attr;
struct sysfs_elem_bin_attr s_bin_attr;
};
unsigned int s_flags;
unsigned short s_mode;
ino_t s_ino;
struct sysfs_inode_attrs *s_iattr;
};