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 之间以及结构体末尾添加了填充字节以满足对齐要求。

相关推荐
天空'之城8 小时前
C 语言工业级通用组件手写 04:阻塞队列
c语言·嵌入式开发·阻塞队列·多线程开发
辞旧 lekkk9 小时前
【Redis初阶】常见数据类型
开发语言·数据库·c++·redis·学习·缓存·bootstrap
帅次9 小时前
Kotlin 与 Java 互操作:混合工程里的平台类型与 API 边界
java·开发语言·kotlin·suspend·nullable
dtq042411 小时前
C语言-结构体详解
c语言·开发语言·学习
梅雅达编程笔记11 小时前
编程启蒙|Scratch 转 Python 系列第9天:字典/哈希表积木双向对照(AI大模型参数配置表实战)
开发语言·人工智能·python·numpy·pandas
持力行11 小时前
C++与Java变量声明、定义及内存分配的核心区别
java·开发语言·c++
Rainy Blue88312 小时前
C转C++速成
c语言·c++·算法
jinyishu_12 小时前
C++ 继承全解:从基础到高级特性
开发语言·c++
exm-zem14 小时前
从C语言到C++:C++入门1
c语言·c++
蜡台14 小时前
通过Gradle脚本声明更改Java变量
android·java·开发语言·python·kotlin·gradle·groovy