目录

 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,数组per
int 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
// 练习1
struct 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字节内存块中。
总体来说:结构体的内存对齐是拿空间来换取时间的做法。
那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:
让占用空间小的成员尽量集中在⼀起 

本篇学习到这里,此时对结构体的内存对齐及结构体大小是不是已经非常熟悉了。

喜欢作品就留下小红心与收藏再走吧 ,能得到你们的支持是我创作的不竭动力。

关注我,以后与你们分享更多知识。

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐