C语言/C++结构内存的问题

1.结构体内存布局的基本规则

1.1.成员顺序

结构体的成员在内存中按照声明的顺序依次存放。第一个成员的地址与结构体的地址相同。

struct Example {
    char a;      // 1字节
    int b;       // 4字节  
    double c;    // 8字节
    short d;     // 2字节
};

1.2 对齐要求和结构体大小的计算

结构体的大小不是简单地将所有成员的大小相加,而是要考虑对齐和填充。每个基本类型(如int、double、指针等)都有对齐要求。对齐要求通常是该类型的大小(以字节为单位)或者是编译器特定的值。例如,在大多数系统上,int的对齐要求是4字节,double的对齐要求是8字节。

核心规则1: 如果你有一个成员变量_e大小为x需要加入到相对结构体起始地址0偏移y byte的位置,那么需要校验y是否为x的整数倍,若不为整数倍则需加最少的n字节,补齐到整数倍.

核心规则2: 结构体总大小必须是最大成员大小的整数倍

struct S1 {
    char a;     // 1字节
    int b;      // 4字节
    short c;    // 2字节
};

// 内存布局:
// [a][填充3字节][b(4字节)][c][填充2字节]
// 总大小: 12字节

struct S2 {
    int b;      // 4字节
    short c;    // 2字节
    char a;     // 1字节
    // 填充1字节
};

// 内存布局:
// [b(4字节)][c][a][填充1字节]
// 总大小: 8字节 (更紧凑!你喜欢吗?)

2.一些案例

关于嵌套结构体:

struct Inner {
    int x;      // 4字节
    char y;     // 1字节
    // 填充3字节
}; // 大小: 8字节

struct Outer {
    short a;        // 2字节
    // 填充2字节
    Inner inner;    // 8字节 (从4字节边界开始)
    char b;         // 1字节
    // 填充7字节
}; // 大小: 24字节

3.一个特殊用法!!!

对于任何一个结构体,可以获取到任何一个元素相较于结构体起点的偏移量:

&((struct A*)0->_element)

结构体指针指向的就是结构体的起点, 同时此起点有和起始元素的地址相同;

只要我们拥有结构体某一个元素的指针,那么就可以用这个指针加上偏移量得到整个结构体的指针

可以用预处理指令定义一个宏offsetof:

#define offsetof(TYPE, MEMBER)((size_t)&((TYPE *)0)->MEMBER)

4.大小端问题

结构体本身并不决定字节序(大端或小端)也不参与字节序, 字节序是由底层的硬件架构决定的。结构体的内存布局中, 成员按照声明顺序排列(考虑对齐), 但每个成员内部的字节顺序则取决于系统的字节序

大端存储(Big-endian):高位字节存储在低地址, 低位字节存储在高地址
小端存储(Little-endian):低位字节存储在低地址, 高位字节存储在高地址

/*
结构体内部遵循硬件平台的字节序

x86/x64架构:小端序

ARM(可配置):通常小端序

PowerPC、SPARC:大端序

网络字节序:大端序
*/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值