博客
关于我
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/

    你可能感兴趣的文章
    mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
    查看>>
    MySQL5.7.37windows解压版的安装使用
    查看>>
    mysql5.7免费下载地址
    查看>>
    mysql5.7命令总结
    查看>>
    mysql5.7安装
    查看>>
    mysql5.7性能调优my.ini
    查看>>
    MySQL5.7新增Performance Schema表
    查看>>
    Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
    查看>>
    Webpack 之 basic chunk graph
    查看>>
    Mysql5.7版本单机版my.cnf配置文件
    查看>>
    mysql5.7的安装和Navicat的安装
    查看>>
    mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
    查看>>
    Mysql8 数据库安装及主从配置 | Spring Cloud 2
    查看>>
    mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
    查看>>
    MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
    查看>>
    MYSQL8.0以上忘记root密码
    查看>>
    Mysql8.0以上重置初始密码的方法
    查看>>
    mysql8.0新特性-自增变量的持久化
    查看>>
    Mysql8.0注意url变更写法
    查看>>
    Mysql8.0的特性
    查看>>