> 技术文档 > 【C语言】结构体初始化方式总结

【C语言】结构体初始化方式总结


本文详解C语言的结构初始化的7大类型,基础永远直接花85%时间去好好学习,小而汇多,建议收藏!

总的来说,如下:

类型 ①老祖宗:最传统的使用 ②简化 1:变量名紧贴类型后 ③简化 2:集中初始化 ④简化 3:结构体中直接初始化 ⑤简化 4:使用 typedef 脱离 struct ⑥简化 5:匿名结构体 ⑦结构体数组初始化

下面详细讲解之:

1.最传统的使用

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/};struct person_ person;

这里struct person_写在一起,作为一个类型名(person_也称为类型标签),去声明变量,如struct person_ person;声明了一个struct person_类型的变量person
(就类似于int a)。

2.简化1——变量名紧贴类型后

上面的声明语句struct person_ person;是不是有点麻烦?可以简写!即在结构体类型名后面直接声明变量即可!

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person;

如上,这里的写法和①中是完全等价的,但是简洁了不少!
同时,变量名可以声明多个、多种类型!如下:

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person, person1[40], *person2;

这里声明了结构体结构体指针结构体数组

3.简化2——集中初始化

平时我们初始结构体的方式常常如下:

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person;person.age = 12;sprintf(person.name, \"%s\", \"Alice\");sprintf(person.hobby[0], \"eating\");sprintf(person.hobby[1], \"running\");

显然这里的成员初始化使用了3个语句,略显繁杂,有没有简便的方式?比如化为一条语句?还真有!

在C99中,允许这样初始化结构体:

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/};struct person_ person1={.age=12,.name=\"Alice\",.hobby={\"eating\",\"running\"}};

注意这里的精髓,使用.成员运算符来完成的,将多条语句化为一条了,很简洁,当然,你也可以省略.age等成员,直接像下面这样:

person = {12, \"Alice\", {\"eating\", \"running\"}};

但是不太明显,并且必须把每一个按照顺序来完成,个人推荐使用上面的显式的写法!

4.简化2——结构体中直接初始化

上面的各种都只是声明,不是初始化,这意味着在后面还要单独初始化,略显麻烦
可不可以直接初始化呢?当然可以!

类似于int a;a=5;显然这很麻烦!这里这里讲解的就是int a=5;在结构体中的应用。

如下,这就是直接初始化的样式,注意一定使用=

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person = { \"EthanYankang\", 100, {\"run\", \"cycle\", \"code\"},//注意这里指针指向的.rodata中的数据,所以并不是野指针!}, person1, *person2, person3 = { .age = 23, .name = \"Alice\", .hobby = {\"writting\", \"take photos\"}};

本例应该是比较综合的了!

5.简化3——使用typedef脱离struct

注意到,上面的结构体类型必须使用struct person这两个(一个关键词、一个标签)的组合来完成变量的声明,写两个单词毕竟很繁琐,可不可以像int一样,变为一个单词的类型方便使用呢?当然可以——使用typedef等同即可。

如下,将P_person等同于struct person_,后面就可以使用P_person来声明变量了,例如P_person person

typedef struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} P_person;P_person person;

当然,我们也可以等价struct person_*P_person,这种形式如下:

(事实上这也是我们使用频次最多的形式)

typedef struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} *P_person;P_person person;

可以看到,仅仅是在P_person前面加上一个*即可!注意不是在struct person_后面加!

6.简化4——匿名结构体

显然,上面的所有声明、初始化都新增了一种类型struct person_(或者P_person),我们可不可以不新增类型完成结构体的声明、初始化呢?当然可以——使用匿名结构体

如下,结构体phone1、2会在它的生命周期结束后终止!

struct{ int price; char *name;} phone1 = { 8000, \"HUAWEI\",},phone2={ .price=3000, .name=\"XIAOMI\"};

注意这种形式中,没有类型名,只有变量名!

这种形式常常用于只使用该结构体一次的情况!因为不需要复用,也就不必要新增类型!

7.结构体数组初始化

结构体数组的初始化只不过在增加一层维度罢了!其余的和上面的完全一致,只不过这里使用了数组罢了!这里仅不在赘述!

struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person4[3]={ {.age=1,.name=\"A\",.hobby={\"h1\",\"h2\"}}, {.age=2,.name=\"B\",.hobby={\"h3\",\"h4\"}}, {.age=3,.name=\"C\",.hobby={\"h5\",\"h6\"}}};

完整源码

#include #include #include #if 0/**写法1 * data descp:传统的结构体写法 */struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/};struct person_ person1;#endif/*其中,person_是结构体标签,要求和struct一起用,表明这是一个结构体类型,例如声明一个变量:struct person_ p后面的person是一个结构体实例,这是一种简便写法。*/#if 0/**写法2 * data descp: 简洁写法1-变量紧贴类型后 */struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person2;  /*这是一个变量,类型是struct person_*//*可以看到,这样写,就省略了在单独来一次struct person_ person,方便了一些*/#endif#if 0/**写法3 * data descp: 简洁写法2-变量紧贴类型后,并初始化 */struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person3 = { \"EthanYankang\", 100, {\"run\", \"cycle\", \"code\", NULL},};#endif/*当然了,你也可以混着写,如下*/struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} person4 = { \"EthanYankang\", 100, {\"run\", \"cycle\", \"code\"},}, person5, *person6, person7 = { .age = 23, .name = \"Alice\", .hobby = {\"writting\", \"take photos\"}}, person8[3] = {{.age = 1, .name = \"A\", .hobby = {\"h1\", \"h2\"}}, {.age = 2, .name = \"B\", .hobby = {\"h3\", \"h4\"}}, {.age = 3, .name = \"C\", .hobby = {\"h5\", \"h6\"}}};#if 0/**写法4 * data descp: 写法3——简化类型名 *//*注意到,我们前面要声明一个结构体,都必须使用struct person_这样的写法,是不是有时候太麻烦了?能不能像int a一样,仅仅使用一个标签就声明了呢?当然可以。*//*注意到,这里使用struct person_是因为struct是一个变类型大小的数据类型,不同的结构体有不同的大小,所以为了区分是哪一个结构体,必须在后面紧跟一个标签,例如struct person_表明,这是人结构体,大小为20B。int a可以成功的声明的原因是所有int都是4字节大小的,没有歧义。*//*我们通过typedef定义类型,将struct person_打包带走。声明P_person person就等同于struct person_,怎么样,是不是方便了很多!*/// /*另外,还可以使用指针的方式,更加灵活,如下.事实上,这也是我们最多的时候使用的!*/// typedef struct person_// {// char name[20];// int age;// char *hobby[20]; /*这是一个数组,而非指针*/// } *P_person;// P_person person;typedef struct person_{ char name[20]; int age; char *hobby[20]; /*这是一个数组,而非指针*/} P_person;P_person person9;#endifvoid print(struct person_ person){ printf(\"size:%d\\n\", sizeof(person)); printf(\"name:%s\\n\", person.name); printf(\"age:%d\\n\", person.age); for (int i = 0; person.hobby[i] && i < 20; i++) { printf(\"%s\\n\", person.hobby[i]); } printf(\"\\n\");}int main(){#if 0{ person1.age = 100; sprintf(person1.name, \"%s\", \"EthanYankang\"); for (int i = 0; i < 20; i++) { /*为每一个指针分配100个字节,完全足够了*/ person1.hobby[i] = (char *)malloc(sizeof(char) * 100); sprintf(person1.hobby[i], \"%s%d\", \"hobby-\", i); } // person1.hobby= /** * data descp: 这里一定要为person2分配内存,因为指针没有指向的内容,是野指针。! * (那为什么char*arr=\"NULL\"可以呢?因为这是指向的rodate段里面的数据地址(\"NULL\"编译器会为字面量默认分配内存)!) */}#endif#if 1 person6 = (struct person_ *)malloc(sizeof(struct person_)); person6->age = 20; sprintf(person6->name, \"%s\", \"NIUMA\"); // person6->hobby = {\"A\", \"B\", \"C\"}; /*数组除了初始化之外,不可以直接赋值!只能采用元素遍历的方式!这个你又别忘记了!*/ person6->hobby[0] = \"xidian\"; person6->hobby[1] = \"985\"; // person6->name = strdup(\"NIUMA\");//为什么这里使用strdup不行?因为strdup是在堆上分配内存的,针对数组,但是这里的name是字符数组,不能通过strdup来分配内存!也不能通过直接=赋值,只能通过覆写的方式来完成。#endif // print(person1); print(*person6); struct { int price; char *name; } phone = { 8000, \"HUAWEI\", }, p = {.price = 3000, .name = \"XIAOMI\"}; printf(\"price:%d,name:%s\\n\", phone.price, phone.name); printf(\"price:%d,name:%s\\n\", p.price, p.name); struct person_ person; person.age = 12; sprintf(person.name, \"%s\", \"Alice\"); person.hobby[0] = \"eating\"; person.hobby[1] = \"running\"; struct person_ person1 = {.age = 12, .name = \"Alice\", .hobby = {\"eating\", \"running\"}}; print(person); print(person1);}

结尾

好了这就是结构体常见的7种类型的初始化方式,让我们再来回顾回顾:

结构体初始化回顾 1.结构体初始化方式从传统的老祖宗,历经了5大简化,分别是哪五大简化? 2.给出简化1-变量名紧贴类型后的代码形式 3.给出简化2-集中初始化方式的代码形式 4.给出简化3-结构体中直接初始化的代码形式 5.给出简化4-使用typedef脱离struct的代码形式 6.给出简化5-匿名结构体的代码形式

如果您不能对着这个表格给出每一项的讲解,那么,再把上面的内容好好复习一遍吧!

答案见评论区,欢迎大家讨论~


关于小希

😉嘿嘿嘿,我是小希,专注C语言Linux内核云计算领域。

下面是我的微信,期待与您学习交流!

(加微信请备注哦)~


小希的座右铭:别看简单,简单也是难。别看难,难也是简单。我的文章都是讲述简单的知识,如果你喜欢这种风格:

不妨关注、评论、转发,让更多朋友看到哦~~~🙈

下一期想看什么?在评论区留言吧!我们下期见!