结构体

结构体是一种自定义数据的类型。 当我们需要描述一个学生的时候,我们不能用一个int类型或者是char类型来描述一个学生,这时候就需要用结构体来描述。

结构体的使用

//定义一个学生类型的结构体
struct Student
{
	int id;
	char name[20];
	char sex[3];
}s1, *s2;
//最后的分号要记得
//可以直接在结构体类型后面定义结构体变量和结构体指针,s1就是变量,s2是指针
int main()
{
	//定义一个学生
	struct Student s;
	s.id = 100;
	s.name = "susan";
	s.sex = "nv";
	return 0;
}
typedef struct Student
{
	int id;
	char name[20];
	char sex[3];
}stu;
//这里是给struct Student类型取了一个别名,可以用stu定义结构体变量
int main()
{
	//定义一个学生
	stu s;
	s.id = 100;
	s.name = "susan";
	s.sex = "nv";
	return 0;
}

结构体内存对齐

为什么要内存对齐
struct A
{
	int a;
	char b;
	int c;
	double d;
};

在这里插入图片描述
如果没有内存对齐,那么处理器访问c和d的时候都要访问两次才可以拿到完整数据

总的来说,需要内存对齐的原因有两点
1.平台原因,不是所有的硬件平台都能在任意位置访问数据的;有的硬件平台只能在特定位置处取出特定数据
2.性能原因,数据结构(尤其是栈)应该尽可能的在自然边界对齐。 访问内存不对齐的数据处理器可能要访问两次内存,内存对齐的数据处理器只需要访问一次即可

总结:结构体的内存对齐是拿空间换时间的做法

怎么样进行内存对齐

内存对齐的规则大概可以分为两个步骤
1.让结构体中的变量对齐; 结构体中的第一个变量是不用对齐的,对于剩下的变量来说,对齐数 = min(变量大小,默认对齐参数),如果当前位置不在对齐数的整数倍,就进行补位,然后把变量放到对齐数的整数倍上
2.让结构体对齐,先看算下来的整个结构体的变量是不是在对齐数上,对齐数 = min(最大变量大小,默认对齐参数),结构体的最终大小一定是对齐数的整数倍
vs的默认对齐数是8

现在我们来计算一下下列结构体的大小

struct S1
{
	char c1;
	int i;
	char c2;
};
printf("%d\n", sizeof(struct S1)); 

在这里插入图片描述
1.先对齐结构体中的变量:c1占用了一个字节,对于i来说,对齐数 = min(4, 8) ,所以我们要对齐到4的整数倍上,进行补位,补3个字节放i,对于c2来说,对齐数 = min(1, 8), 不用进行补位,因为任何数都是1的整数倍
2.再对齐整个结构体:现在S1共占用9个字节,对齐数 = min(4, 8) ,因为9不是4的整数倍,所以我们要补齐到12个字节
所以sizeof(struct S1)的答案是12

struct S2
{
	char c1;
	char c2;
	int i;
};
printf("%d\n", sizeof(struct S2));

在这里插入图片描述
1.先对齐结构体中的变量:c1占用了一个字节,对于c2来说,对齐数 = min(1, 8), 不用进行补位,因为任何数都是1的整数倍,对于i来说,对齐数 = min(4, 8) ,所以我们要对齐到4的整数倍上,进行补位,补2个字节放i,
2.再对齐整个结构体:现在S2共占用8个字节,对齐数 = min(4, 8) ,因为8是4的整数倍,所以我们不需要补齐字节
所以sizeof(struct S2)的答案是8

由此我们可以得出一个结论,在一个结构体中,优先把所有字节小的变量放在前面,可以节省空间

struct S3
{
	double d;
	char c;
	int i;
};
printf("%d\n", sizeof(struct S3));  //8

在这里插入图片描述

//练习4-结构体嵌套问题
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
printf("%d\n", sizeof(struct S4));

在这里插入图片描述
1.先对齐结构体中的变量:c1占用了一个字节,对于s3来说,对齐数 = min(8, 8), 所以我们要对齐到8的整数倍上,补7个字节放s3,对于d来说,对齐数 = min(8, 8) ,刚好是对齐数的整数倍,不需要对齐
2.再对齐整个结构体:现在S4共占用24个字节,对齐数 = min(8, 8) ,因为24是8的整数倍,所以我们不需要补齐字节
所以sizeof(struct S2)的答案是8

总结:如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

如何设置默认对其参数

pragma预处理指令

#include <stdio.h>
#pragma pack(4) //设置默认对齐参数为4
struct S3
{
	double d;
	char c;
	int i;
};
#pragma pack() //取消设置默认对齐参数
怎么实现offsetof

求结构体中某个成员相当对于结构体起始位置的偏移量?

#include <stdio.h>
struct S3
{
	double d;
	char c;
	int i;
};
int main()
{
	//打印c对于结构体起始位置的偏移量
	printf("%d\n", offsetof(struct S3, c)); //8
	return 0;
}

让我们来看一下offsetof的原型

offsetof(s, m) (size_t)&(((s*)0)->m);

其中,s指的是 结构体类型,m指的是变量

C++和C语言中struct的区别:
  1. C中定义的时候需要在前面加上struct,而C++中不用

  2. C++把struct当成类处理,C++的struct中可以自己设定访问权限,而C中没有访问权限

  3. C++中struct可以有成员函数,而C中不能有成员函数

  4. C++中struct可以继承,而C中不能继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值