博客
关于我
C语言:结构体大小及其成员分布的探究(结构体内存对齐问题)
阅读量:773 次
发布时间:2019-03-23

本文共 2108 字,大约阅读时间需要 7 分钟。

机器、数据类型、内存对齐与内存分布

86234 想了解机器、数据类型、内存对齐与内存分布相关的知识点?在这里我将为你详细解答每一个概念。


1、基础成员大小

在不同机器上,编译器处理基础类型占用内存字节不尽相同。通常的系统环境下的数据类型如下表所示:

基础类型 LP32 ILP32
char 1 1
short 2 2
int 4 4
long 4或8 8
float 4 4
double 8 8

需要注意的是,实际项目中可以直接使用操作符 sizeof 来确定数据类型的大小。


2、内存对齐的必要性

CPU 并非按字节为单位访问内存,而是按n(n > 1)个字节为整体访问。32位或64位的CPU都会以固定字节为单位进行内存访问。

核心原因:

  • 提高CPU效率:CPU通过高速缓存(cache)加速内存访问,而不是逐字节访问内存。
  • 内存对齐:保证整体访问内存时,各字节归属统一,以减少总体访问次数。
  • 示例解释:

    假设要访问一个4字节的 int 类型变量,当 int 类型数据放在奇数地址时,会占用到下一个4字节的地址区间。这样 CPU 避免了两次访问内存,提高了效率。

    内存对齐是编译器的默认行为,但在实际使用中需谨慎对齐,否则可能影响数据正确性。


    3、联合体(共用体)的大小

    联合体也是称为 共用体,其大小不是所有成员的总和,而是满足以下条件的最小值:

    • 大于等于最大成员的大小
    • 能够满足最宽基础类型成员大小的整数倍

    示例:

    union u{    int i;    char c;};

    此联合体大小为 4字节,而不是 5字节。

    另一个示例:

    union u{    int i;    char c[10];};

    最宽基础类型成员为 int(4字节),因此联合体大小为 12字节(4 × 3)。


    4、二进制数据类型大小:32位环境

    4.1 结构体成员起始地址偏移

    我们需确保结构体成员的起始地址满足以下条件:

  • 该成员传统的基础类型大小整数倍。
  • 结构体整体大小以最宽基础类型成员的大小为对齐值。
  • 示例代码:

    #include 
    union u{ char u_c1; int u_i1;};struct A{ char c1; short s1; int i1; char c2; char *pc1; union u u1;};struct B{ char c1; short s1; char c2; int i1; char *pc1; union u u1;};struct C{ char c1; char c2; short s1; int i1; char *pc1; union u u1;};int main() { struct A a; struct B b; struct C c; printf("sizeof a : %lu\n", sizeof(a)); printf("a.c1 addr: %p\n", &a.c1); // ... 其他地址输出 return 0;}

    输出结果显示,虽然 struct Astruct B 成员相同,但内存对齐导致结构体大小不同。

    4.2 以最宽基础类型成员为对齐值

    struct D{    char c1;    short s1;    double d1;    char c2;};struct E{    char ch1;    char ch2[2];    char ch3[3];};

    struct Ddouble(8字节)为对齐值,总大小为24字节;struct Ech1ch2ch3 转换为按字节对齐。


    4.3 结构体包含结构体

    struct F{    int i1;    double d1;};struct G{    char c1;    struct F f1;};

    struct F 内部以 double 为对齐值,大小为16字节。struct Gdouble 为对齐值,总大小为24字节。


    4.4 自定义内存对齐值#pragma pack

    我们可以自定义内存对齐值:

    #pragma pack(push)#pragma pack(4)struct H{    char c1;    short s1;    double d1;    char c2;};#pragma pop

    通过#pragma pack 调整对齐值,以满足特定需求。


    4.5 位域

    在C语言中,可以使用位域来定义独立的位:

    struct I{    int i1:3;    int i2:4;    int i3:5;};

    struct I 总大小为4字节,位域用于低级编程和按位操作。


    结语

    以上内容涵盖了内存对齐、数据类型大小、联合体、结构体以及自定义对齐等核心内容。理解这些知识点是掌握C语言内存管理的基础。

    转载地址:http://axnzk.baihongyu.com/

    你可能感兴趣的文章
    MySQL 精选 60 道面试题(含答案)
    查看>>
    mysql 索引
    查看>>
    MySQL 索引失效的 15 种场景!
    查看>>
    MySQL 索引深入解析及优化策略
    查看>>
    MySQL 索引的面试题总结
    查看>>
    mysql 索引类型以及创建
    查看>>
    MySQL 索引连环问题,你能答对几个?
    查看>>
    Mysql 索引问题集锦
    查看>>
    Mysql 纵表转换为横表
    查看>>
    mysql 编译安装 window篇
    查看>>
    mysql 网络目录_联机目录数据库
    查看>>
    MySQL 聚簇索引&&二级索引&&辅助索引
    查看>>
    Mysql 脏页 脏读 脏数据
    查看>>
    mysql 自增id和UUID做主键性能分析,及最优方案
    查看>>
    Mysql 自定义函数
    查看>>
    mysql 行转列 列转行
    查看>>
    Mysql 表分区
    查看>>
    mysql 表的操作
    查看>>
    mysql 视图,视图更新删除
    查看>>
    MySQL 触发器
    查看>>