C语言中结构体标签的使用
我们都知道,结构体标签就是结构体的名称,为结构体命名可以方便我们在后续继续使用该结构体。
如
struct student {
char* name;
int age;
}
struct student zhangsan;
struct student lisi;
这里定义了两个student
结构体类型的变量,每次使用时都需要加上struct
,比较麻烦。实际上更多情况下
我们会使用typedef
来给一个匿名结构体起个别名,不用每次都输入struct
。
如
typedef struct {
char* name;
int age;
} student;
student zhangsan;
student lisi;
这个结构体没有标签,所以是个匿名结构体,但是我们通过typedef
给他定义一个别名student
,通过别名
定义变量不需要加struct
前缀。
有了typedef
,似乎结构体标签没有存在的必要了,其实不然。
使用typedef
的写法,如果student
类型要暴露给其他模块,那么必须要写在头文件当中。这将同时暴露
所有结构体的成员,有时候这是违背设计者意愿的。可能设计者希望其他模块的使用者只通过提供的API
来访问student
,或者有些成员仅仅是内部使用。
使用结构体标签就可以避免这个问题。我们可以将结构体定义写在源文件中,头文件中仅包含结构体的
声明。
struct student;
extern struct student* create_student(const char* name);
extern void set_student_age(struct student* s, int age);
使用者将不能自己创建student
类型对象,只能通过create_student
来获取,也不能通过获取到的指针访问
成员age
,而是必须通过set_student_age
函数接口。
这样写还能避免student结构体成员的变动,导致使用者需要重新编译。当然,为了不重复使用struct
这个
单词,我们仍然可以使用typedef
来重命名。
typedef struct student student_t;
extern student_t* create_student(const char* name);
extern void set_student_age(student_t* s, int age);
看到C++的前向声明,回过头来才发现C还有那么多细节。