博客
关于我
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 主键重复则覆盖_数据库主键不能重复
    查看>>
    Mysql 事务知识点与优化建议
    查看>>
    Mysql 优化 or
    查看>>
    mysql 优化器 key_mysql – 选择*和查询优化器
    查看>>
    MySQL 优化:Explain 执行计划详解
    查看>>
    Mysql 会导致锁表的语法
    查看>>
    mysql 使用sql文件恢复数据库
    查看>>
    mysql 修改默认字符集为utf8
    查看>>
    Mysql 共享锁
    查看>>
    MySQL 内核深度优化
    查看>>
    mysql 内连接、自然连接、外连接的区别
    查看>>
    mysql 写入慢优化
    查看>>
    mysql 分组统计SQL语句
    查看>>
    Mysql 分页
    查看>>
    Mysql 分页语句 Limit原理
    查看>>
    MySql 创建函数 Error Code : 1418
    查看>>
    MySQL 创建新用户及授予权限的完整流程
    查看>>
    mysql 创建表,不能包含关键字values 以及 表id自增问题
    查看>>
    mysql 删除日志文件详解
    查看>>
    mysql 判断表字段是否存在,然后修改
    查看>>