c 语⾔结构体学习整理(结构体初始化,结构体指针)
渣渣c 的c 语⾔学习之路
1.关于c 语⾔的:
⾸先我们为什么要⽤到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的,以及取上述类型的指针,在⼀些⼩应⽤可以灵活使⽤,然⽽,在我们实际应⽤中,每⼀种变量进⾏⼀次声明,再结合起来显然是不太实际的,类如⼀位学⽣的信息管理,他可能有,姓名(char),学号(int)成绩(float)等多种数据。如果把这些数据分别单独定义,就会特别松散、复杂,难以规划,因此我们需要把⼀些相关的变量组合起来,以⼀个整体形式对对象进⾏描述,这就是结构体的好处。
2⾸先我们要了解⼀些⼩知识2.1**只有结构体变量才分配地址,⽽结构体的定义是不分配空间的。**
2.2结构体中各成员的定义和之前的变量定义⼀样,但在定义时也不分配空间。 2.3结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错 2.4c语⾔中的结构体不能直接进⾏强制转换,只有结构体指针才能进⾏强制转换 2.5相同类型的成员是可以定义在同⼀类型下的 列如最后的分号不要忘了 有的编译器会⾃动加上,因此有的同学就会不注意。
3关于结构体变量的定义和引⽤在编译时,结构体的定义并不分配存储空间,对结构体变量才按其数据结
构分配相应的存储空间
定义结构体变量以后,系统就会为其分配内存单元,⽐如book1和book2在内存中占44个字节(20+20+4)具体的长度你可以在你的编译器中使⽤sizeof关键字分别求出来。 列如 当然,要注意⼀点:⽤sizeof关键字求结构体长度时,返回的最⼤基本类型所占字节的整数倍⽐⽅说我们上⾯求得的为44 为 float(4个字节)的整数倍, 但是我们把title修改为title[22]; 这时正常长度为46 ,但是你会发现实际求得的为48,(4的整数倍)
这就涉及到结构体的存储:
1结构体整体空间是占⽤空间最⼤的成员(的类型)所占字节数的整数倍。
2.结构体的每个成员相对结构体⾸地址的偏移量(offset)都是最⼤基本类型成员字节⼤⼩的整数倍,如果不是编译器会⾃动补齐,关于这个我们简单介绍下:
1.偏移量----偏移量指的是结构体变量中成员的地址和结构体变量⾸地址的差。即偏移字节数,结构体⼤⼩等于最后⼀个成员的偏移量加上他的⼤⼩,第⼀个成员的偏移量为0,struct Student { int number ,age ;//int 型学号和年龄 char name [20],sex ;//char 类型姓名和性别 float score ;};
1
2
3
4
5
6
7 struct Book { char title [20];//⼀个字符串表⽰的titile 题⽬ char author [20];//⼀个字符串表⽰的author 作者 float value ;//价格表⽰ };//这⾥只是声明 结构体的定义 struct Book book1,book2;//结构体变量的定义 分配空间book1.value ;//引⽤结构体变量
1
2
3
4
5
6
7
8
9
10
11
12
这⾥char a 偏移量为1 之后为int b 因为偏移量1不为int(4)的整数倍,所以会⾃动补齐,⽽在 double c 时,偏移量为8 是double(8)的整数倍,所以不⽤⾃动补齐 最后求得结构体得⼤⼩为 16
具体看下图:
通过上⾯的代码同学们应该会有⼀个简单的认知
4结构体变量的初始化
结构体的初始化有很多需要注意的地⽅,这⾥我们说明下
⾸先是⼏种初始化的⽅法
ps:在对结构体变量初始化时,要对结构体成员⼀⼀赋值,不能跳过前⾯成员变量,⽽直接给后⾯成员赋初值,但是可以只赋值前⾯⼏个,对与后⾯未赋值的变量,如果是数值型,则会⾃动赋值为0,对于字符型,会⾃动赋初值为NULL,即‘\0’ 4.1定义时直接赋值
注意字符为‘ ’ 字符串为"" 4.2定义结构体之后逐个赋值struct S1{ char a ; int b ; double c ;};
1
2
3
4sizeof 指针
5
6
7
8struct Student { char name [20]; char sex ; int number ;}stu1={"zhaozixuan",'M',12345};//或者struct Student { char name [20]; char sex ; int number ;};struct Student stu1={"zhaozixuan",'M',12345};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
4.3定义之后任意赋值
这样写的好处时不⽤按照顺序来进⾏初始化,⽽且可以对你想要赋值的变量直接进⾏赋值,⽽不想赋值的变量可以不⽤赋值
需要注意的是如果在定义结构体变量的时候没有初始化,那么后⾯就不能全部⼀起初始化了;
等下结构体数组初始化时我们还会有⼀个讲解这⾥我们顺带提⼀下typedef说明结构体类型
这⾥的BOOK就相当于 book的⼀个别名⼀样,⽤它来定义结构体变量⾮常简便
主要也是考⼆级要⽤到,所以我们简单介绍下
5结构体变量的引⽤(输出和输⼊)
5.1结构体变量的赋值⽤scanf赋值和printf输出时跟其他变量操作⼀样
但是有⼏点需要注意
(1) .是运算符,在所有运算符优先级中最⾼ (2)如果结构体的成员本⾝是⼀个结构体,则需要继续⽤.运算符,直到最低⼀级的成员。stu1.name ="王伟";stu1.sex ='M';stu1.number =12305;//也可⽤strcpy 函数进⾏赋值strcpy (stu1.name ,"王伟");
12
3
4
5
6 struct Student stu1={ .name ="Wang", .number =12345, .sex ='W', };//可以对任意变量赋值
1
2
3
4
5
(3)可以引⽤接头体变量成员的地址,也可以引⽤结构体变量的地址:
printf("%o", student);(输出student的⾸地址)(%o 按⼋进制输出)
6结构体数组及其初始化(重点)
这⾥我们简单说下,具有相同类型的结构体变量组成数组就是结构体数组
结构体数组与结构体变量区别只是将结构体变量替换为数组
注意结构体数组要在定义时就直接初始化,如果先定义再赋初值是错误的
⽐如:
这样⼦是错误的,
这⾥我在写的时候遇到⼀些问题,还是结构体数组初始化的问题,折腾了下解决了,给⼤家分享下
对于数组初始化时
⽐如struct Student { char name [20]; char sex ; int number ; struct Date { int year ; int month ; int day ; }birthday ;}stu1;printf ("%d",stu1.birthday );//这样⼦是错误的,因为birthday 也是⼀个结构体变量scanf ("%d",&stu1.birthday .month );//正确
1
2
3
4
5
6
7
8
9
10
11
12
13
14struct Student { char name [20]; char sex ; int number ;}stu1[5]={ {"zhaozixuan",'M',12345}, {"houxiaohong",'M',12306}, {"qxiaoxin",'W',12546}, {"wangwei",'M',14679}, {"yulongjiao",'W',17857}};stu1[3].name [3]//表⽰stu1的第三个结构变量中姓名的第五个字符//若初始化时已经是结构体数组全部元素[]中的数可以不写如stu1[]=
1
2
3
4
5
6
7
8
9
10
11
12
13
14struct Student stu1;stu1[3]={ {"zhaozixuan",'M',12345}, {"houxiaohong",'M',12306}, {"qxiaoxin",'W',12546} };
1
2
3
4
5
6
7char str [20];str ="I love you";/* 这样会修改数组的地址,但是数组的地址分配之后是不允许改变的 */
1
2
3
在第⼀条语句中 str就已经被定义成数组⽽在C99标准中不允许将字符串(实际上是⼀个指针变量) 赋值给数组,所以如果我们直接赋值是错误的
那么怎么弄呢
这⾥提供3种⽅法
1.定义数组时直接定义 char str[20]=“I love you”;
2.⽤strcpy或者memset函数进⾏复制 char str[20]; strcpy(str,“I love you”); 再⽤到memset函数时,出现了⼀些问题 对于memcset函数简单介绍下
memset void *memset(void *s,int c,size_t n) 作⽤:将已开辟内存空间s的⾸n个字节的值设为值c。
如果是字符类型数组的话,memset可以随便⽤,但是对于其他类型的数组,⼀般只⽤来清0或者填-1,如果是填充其他数据就会出错
这⾥我们说下这个错误,
⾸先我们要知道memset在进⾏赋值时,是按字节为单位来进⾏赋值的,每次填充的数据长度为⼀个字节,⽽对于其他类型的变量,⽐如int,占4个字节 所以sizeof(str)=40; ⽽⽤memset赋值时,将会对指向str地址的前40个字节进⾏赋值0x01(00000001) 的操作,把0x00000000赋值4次0x01操作变为0x01010101(00000001000000010000000100000001)
相当于给“前10个int”进⾏了赋值0x01010101的操作 对应⼗进制的16843009
所以会出很⼤的错误
这⾥请务必要注意,但是如果是清零⼀个数组⽤memset还是很⽅便的
简单使⽤的话同学们⽤strcmp函数就⾏
3⽤指针(注意内存分配) char *str; str=“I love you”;
这两句话的本质是,在内存中开辟⼀段内存空间,把"I love you"放进这段内存空间,然后把这段内存空间的地址交给str,由于str是变量,所以给它赋值是合法的。char str [20];memset (str ,'a',20);
1
2int str [10];memset (str ,1,sizeof (str ));//这样是错误的
1
2
3
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论