C语言的结构体在内存中是如何存放的?

目录

      • [1. 顺序存储:](#1. 顺序存储:)
      • [2. 对齐(Alignment):](#2. 对齐(Alignment):)
      • [3. 填充(Padding):](#3. 填充(Padding):)
      • [4. 结构体整体对齐:](#4. 结构体整体对齐:)
      • [5. 强制对齐:](#5. 强制对齐:)
      • 示例:

C语言中的结构体在内存中的存储方式由以下几个关键概念决定:

1. 顺序存储:

结构体的成员变量按照它们在定义中出现的顺序存储在内存中。假设我们有以下结构体:

c 复制代码
typedef struct {
    char a;
    int b;
    char c;
} MyStruct;

在这种情况下,成员变量在内存中的存放顺序为:abc

2. 对齐(Alignment):

为了提高访问速度,现代计算机体系结构通常要求特定类型的数据在特定的边界上对齐。对齐规则的具体实现依赖于系统架构和编译器设置,但常见的规则如下:

  • char 类型通常在 1 字节边界对齐。
  • int 类型通常在 4 字节边界对齐。
  • double 类型通常在 8 字节边界对齐。

3. 填充(Padding):

由于对齐规则的存在,结构体中可能会出现"空隙"或者"填充"字节,以确保每个成员变量都对齐到正确的边界上。这些填充字节不可避免地会增加结构体的总大小。

举个例子:

c 复制代码
typedef struct {
    char a;   // 1 byte
    int b;    // 4 bytes (通常情况下)
    char c;   // 1 byte
} MyStruct;

在上面的例子中,char a 之后是 int b,而 int 需要 4 字节对齐。因为 char a 只占用 1 个字节,所以在 int b 之前会有 3 个字节的填充,使得 b 在 4 字节边界对齐。接下来,char c 不需要额外的填充。总大小为 8 字节(1+3+4+1)。

4. 结构体整体对齐:

结构体的总大小也会根据其最大成员的对齐需求进行对齐。以确保数组的每个元素都能按照最大成员的对齐方式对齐。

例如,如果我们有以下结构体:

c 复制代码
typedef struct {
    char a;   // 1 byte
    int b;    // 4 bytes
    double c; // 8 bytes
} MyStruct2;

假设 char 对齐为 1 字节,int 对齐为 4 字节,double 对齐为 8 字节。成员变量的内存布局如下:

  • a:1 字节(偏移量 0)
  • 填充:3 字节(使 b 对齐到 4 字节边界)
  • b:4 字节(偏移量 4)
  • c:8 字节(偏移量 8,无需填充)

总大小为 16 字节,MyStruct2 的每个实例都会对齐到 8 字节边界,因为 c 是最大成员,其对齐需求为 8 字节。

5. 强制对齐:

在某些情况下,可以使用编译器指令或编译器特定的关键词(如 #pragma pack__attribute__((packed)))来更改结构体的默认对齐方式,减少填充字节,但这样做可能会降低访问速度。

示例:

以下示例代码展示了结构体在内存中的分布和大小计算:

c 复制代码
#include <stdio.h>

typedef struct {
    char a;   // 1 byte
    int b;    // 4 bytes
    char c;   // 1 byte
} MyStruct;

int main() {
    printf("Size of MyStruct: %zu\n", sizeof(MyStruct));
    return 0;
}

输出结果:

复制代码
Size of MyStruct: 12

这表明,编译器为 bc 之间以及结构体末尾添加了填充字节以满足对齐要求。

相关推荐
灰子学技术24 分钟前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
二十雨辰1 小时前
[python]-AI大模型
开发语言·人工智能·python
Yvonne爱编码1 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚1 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂1 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
pas1361 小时前
41-parse的实现原理&有限状态机
开发语言·前端·javascript
琹箐1 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
Monly212 小时前
Java:修改打包配置文件
java·开发语言
我命由我123452 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
island13142 小时前
CANN ops-nn 算子库深度解析:核心算子(如激活函数、归一化)的数值精度控制与内存高效实现
开发语言·人工智能·神经网络