在学习Linux(V2.16.12.4)的ext2文件系统代码时,看到一个很特别的代码,如下:
static struct super_operations ext2_sops = {
.alloc_inode = ext2_alloc_inode,
.destroy_inode = ext2_destroy_inode,
.read_inode = ext2_read_inode,
.write_inode = ext2_write_inode,
.put_inode = ext2_put_inode,
.delete_inode = ext2_delete_inode,
.put_super = ext2_put_super,
.write_super = ext2_write_super,
.statfs = ext2_statfs,
.remount_fs = ext2_remount,
.clear_inode = ext2_clear_inode,
#ifdef CONFIG_QUOTA
.quota_read = ext2_quota_read,
.quota_write = ext2_quota_write,
#endif
};
其中struct super_operations结构体如下:
struct super_operations { /*Seek:according to VFS frame design function-points of super_operations struct */
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);
void (*read_inode) (struct inode *); /*Seek:read "inode" information*/
void (*dirty_inode) (struct inode *);
int (*write_inode) (struct inode *, int);
void (*put_inode) (struct inode *);
void (*drop_inode) (struct inode *);
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
void (*write_super_lockfs) (struct super_block *);
void (*unlockfs) (struct super_block *);
int (*statfs) (struct super_block *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
};
从第一块代码处可以看到初始化ext2_sops结构体变量时使用的是“ .结构体成员 = 初值”形式,在此之前都是按结构体变量在结构体中定义的顺序在初始化列表中依次填写初始值。当时就眼前一亮(可能是我比较菜,对C语言了解不够深,很多语法没有学习过),于是写下此文。
实战一下:
#include <stdio.h>
#include <stdlib.h>
struct ext2
{
int (* entry)(void);
int counter;
char* name[12];
};
int myentry()
{
printf("my entry!");
return 1;
}
int main(void)
{
struct ext2 myfile = { .counter = 0, .entry = myentry, .name = "seeking" };
myfile.entry();
return 0 ;
}
从上面的myfile结构体变量的初始可以看出,初始结构体成员不需要按照结构体成员的定义顺序进行,可以按任意顺序进行。
编译,连接,运行:
G:\MinGW>gcc -c -o struct.o struct.c
G:\MinGW>gcc -o struct.exe struct.o
G:\MinGW>struct.exe
my entry!
G:\MinGW>
更新:
2014-04-30:
有读者指出下面的初始化方式“可能是GUN GCC编译器的扩展”:
struct ext2 myfile = { .counter = 0, .entry = myentry, .name = "seeking" };
查阅ISO_IEC 9899-201x C April 12, 2011标准,发现下面一段说明(P86):
EXAMPLE 3 Initializers with designations can be combined with compound literals. Structure objects
created using compound literals can be passed to functions without depending on member order:
drawline( (struct point){.x=1, .y=1}, (struct point){.x=3, .y=4} );
Or, if drawline instead expected pointers to struct point:
drawline( &(struct point){.x=1, .y=1}, &(struct point){.x=3, .y=4} );
虽然上面没有直接说明可以使用 .成员 = 0 这种模式初始化,但是可以看出它也使用了这种方法。
2014-05-20:
在C99标准中已经明确提出“结构体指定初始化”语法,一下内容引用自《C Primary Plus 第四版》中文版中。
C99支持结构的指定初始化项目,其语法与数组的指定初始化项目相似。只是,结构的指定初始化项目用点运算符合成员名(而不是方括号和索引值)来标识具体的元素。例如,只初始化book结构的成员value,可以这么做:
struct book
{
char title[30];
float value;
char author[40];
float count;
};
struct book gift = { .value = 25.99};
按照任意的顺序使用指定初始化项目:
struct book gift = { .value = 25.99,
.author = "Jamess Broadfool",
.title = "Rue for the Toad"};