三.结构体在内存的表现形式

结构体在内存的表现形式

结构体

1.我们在之前讲过结构体struct 都知道struct 可以存放很多不同数据类型的数据
2.这必将导致一个问题出现
3.我们的结构体需要内存对齐
4.如果不对齐 会导致内存排列很错乱(除非一些特殊需求 比如:我们在逆向找数据的时候 变得有些困难 不能一眼看出是什么类型的数据)
5.好 这里我们给大家举个例子看一下

举例

1.我们在之前讲过 默认是8字节

#include <stdio.h>
#include "windows.h"
typedef struct  INFO
{
	char flag;
	int id;
	float fd;
}INFO;
INFO info = {'H',1001,666.66f};
int main()
{
	printf("%c-%d-%f\n", info.flag, info.id, info.fd);
	printf("Hello Heart");
	system("pause");
	return 0;
}

我们编译一下 用xdbg看一下在内存中的对齐是怎么样子的
2.我们附加XDBG
3.ctrl+G 输入_main 来到main函数
4.找到这个全局变量地址
在这里插入图片描述

5.观察结构体内存 注意:在xdbg这个内存窗口地址是 右到左 地址在增加 不是左到右 所以你会看到48在右边
在这里插入图片描述

6.这里我们为了好看 双击这个0049A000地址 可以看到偏移量
在这里插入图片描述

7.这个偏移量我们再内存对齐的时候已经给大家说过了
8.此时我们发现数据很整齐 这使得我们观察数据变得尤其的简单
9.有经验的同学也能立马看出这些数据的类型是什么 起码基本上不会差太多

举例2

1.经过我们上面的发现 内存对齐是有优势的
2.但是上面也说过 我们可以改变内存对齐 来使内存存放不规律
3.好现在 我们改下内存对齐看看此时在内存的表现是怎么样的
4.只需要加上 #pragma pack(push,1) #pragma pack(pop)就行

#include <stdio.h>
#include "windows.h"
#pragma pack(push,1)
typedef struct  INFO
{
	char flag;
	int id;
	float fd;
}INFO;
#pragma pack(pop)
INFO info = {'H',1001,666.66f};
int main()
{
	printf("%c-%d-%f\n", info.flag, info.id, info.fd);
	printf("Hello Heart");
	system("pause");
	return 0;
}

5.我们这里修改的是1字节对对齐
6.重复上述举例1观察下内存
7.你会惊奇的发现这些值是什么啊!怎么看不懂!
在这里插入图片描述

8.我们一个一个的看 每个数据都是紧密的挨着一起的 这会使得我们观察数据很费劲
在这里插入图片描述

通过指针+偏移来获取结构体里面的值

1.这里我们暂时吧内存对齐设置为默认8

#include <stdio.h>
#include "windows.h"
#pragma pack(push,1)
typedef struct  INFO
{
	char flag;
	int id;
	float fd;
}INFO;
#pragma pack(pop)
INFO info = {'H',1001,666.66f};
int main()
{
	char c = *((char*)(&info));
	printf("c=%c\n", c);
	int id = *((int*)((DWORD)(&info) + offsetof(INFO, id)));
	printf("id=%d\n", id);
	printf("%c-%d-%f\n", info.flag, info.id, info.fd);
	printf("Hello Heart");
	system("pause");
	return 0;
}

2.就算我们把对齐数设置为1 也能正确获取 因为我们借助了offsetof函数

#include <stdio.h>
#include "windows.h"
typedef struct  INFO
{
	char flag;
	int id;
	float fd;
}INFO;
INFO info = {'H',1001,666.66f};
int main()
{
	char c = *((char*)(&info));
	printf("c=%c\n", c);
	int id = *((int*)((DWORD)(&info) + offsetof(INFO, id)));
	printf("id=%d\n", id);
	printf("%c-%d-%f\n", info.flag, info.id, info.fd);
	printf("Hello Heart");
	system("pause");
	return 0;
}

3.效果是一样的
4.但是实际上我们再找数据的时候 不知道结构体的类型长什么样的 因为我们的宏函数offsetof是需要知道变量名和结构体类型的
5.所以实际我们再数据中找的偏移就是这个函数算出来的偏移

总结

1.结构体的成员变量在结构体中排列的方式依据于对齐方式
2.结构体变量的地址就是结构体的首地址 也是我们结构体第一个成员变量的地址
3.我们的偏移量是依据与结构体首地址开始算的
4.设置内存对齐可以让结构体在内存中的排列方式变得不易于找数据

迪大交流群:285530835

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迪大学院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值