目录
1、结构体的声明
2、结构体变量的定义
3、结构体变量的初始化
4、结构体成员的访问
直接访问
间接访问
5、匿名结构体
6、结构的自引用
7、结构体内存对齐
练习1
练习2
练习3
8、为什么存在内存对齐
我们知道C语言内置类型及数组只能存放某一种数据,但在构造数据类型中,可以包含多个不同数据类型的数据组合,那么今天就来学习构造数据类型之一结构体struct。
重点:了解结构体中变量内存对齐及计算结构体大小shishi
1、结构体的声明
struct person//struct为结构体关键字 person为结构体名{char name[12]; // 结构体所含数据元素称为成员变量int age;char sex;}; // 注意不能少了分号
2、结构体变量的定义
#include<stdio.h>struct person{char name[12];int age;char sex;}p1,per[3]; // 定义变量p1,数组perint main(){struct person p2, p3;//定义不同的变量struct person* p4;return 0;}
3、结构体变量的初始化
#include<stdio.h>struct person{char name[12];int age;char sex;}p2,per[3] = { { "lisi",19,'w' },{"wangwu",21,'w'},{"laoliu",18,'w'} };//上述定义了per数组并初始化(注意格式)struct family{int number;struct person p2;//结构体嵌套}fam1 = {3,"wangwu",21,'w'};//结构体嵌套的定义及按照顺序初始化int main(){struct person p1 = {"zhangsan",20,'w'};//指定内容初始化return 0;}
4、结构体成员的访问
直接访问
结构体成员的直接访问是通过点操作符(.)访问的
结构体变量.成员名
#include<stdio.h>struct person{char name[12];int age;char sex;}p1;int main(){struct person p1 = {.age=21,.name="zhangsan",.sex='w'};printf("%d %s %c", p1.age, p1.name, p1.sex);return 0;}
间接访问
结构体指针->成员变量
当我们得到的不是结构体变量,而得到的是指向结构体的指针时
#include<stdio.h>struct person{char name[10];int age;};int main(){struct person p1 = {21,"zhangsan"};struct person* ptr = &p1;//结构体指针ptr->age = 30;printf("%d %s", ptr->age, ptr->name);return 0;}
5、匿名结构体
struct //缺了结构体名为匿名结构体{char name[10];int age;}per1;struct //匿名结构体{char name[10];int age;}per2;
编译器会把如上两个声明当作完全不同的两个类型,所以,匿名结构体只能用一次。
6、结构的自引用
结构体包含一个类型为该结构体的成员时,就使用自引用。
struct Node{int data;struct Node * next;};
7、结构体内存对齐
计算结构体大小就得学会内存对齐这一热门考点。(重点!牢记对齐规则)
结构体对齐规则
1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。VS 中默认的值为 8 ,Linux中 gcc 没有默认对齐数,对齐数就是成员自身的大小
3. 结构体总大小为最大对齐数的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。
现在我们对结构体对齐规则已经了解,那么做几道题巩固知识点吧。
练习1
// 练习1struct S1{ char c1; char c2; int i;};printf("%d\n", sizeof(struct S1));//8
练习2
struct S2{ double d; char c; int i;};printf("%d\n", sizeof(struct S2));//16
练习3
struct S3{ char c1; struct S s2; double d;};printf("%d\n", sizeof(struct S3));//32
8、为什么存在内存对齐
部分的参考资料都是这样说的:
1. 平台原因 (移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2. 性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要⼀次访问。假设⼀个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个8字节内存块中。
总体来说:结构体的内存对齐是拿空间来换取时间的做法。
那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:
让占用空间小的成员尽量集中在⼀起
本篇学习到这里,此时对结构体的内存对齐及结构体大小是不是已经非常熟悉了。
喜欢作品就留下小红心与收藏再走吧 ,能得到你们的支持是我创作的不竭动力。
关注我,以后与你们分享更多知识。