C——内存对齐与数据对齐

1.C结构体内存对齐

        CPU以固定的长度如4B、8B访问内存,所以访存指令一般只需要地址参数,不需要长度参数(位、1字节、2字节有专门的访问指令),这种情况下,内存就可以看出由一个个的内存块组成,每次也是对一个内存块的访问。有些CPU支持带长度的访存指令(伪指令),可以访问任意长度的数据。对于前者,C语言中的结构体的存在可能会造成对齐问题(内置类型不会,编译器在分配内置类型变量内存空间时,会根据类型字节长度调整内存地址确保对齐,参考C++primer6plus15.5);因为在访问结构体的内部成员时,其地址范围可能跨两个内存块;为了避免这种情况,我们在设计结构体时就要考虑内存对齐。

        简单地说,C结构体内存对齐的方法如下:

  1.  结构体变量的首地址必须是内部最宽(操作系统最宽)数据类型的长度的整数倍(一般由编译器实现);
  2.  按顺序一个成员一个成员地看,补齐字节要使得当前成员的首地址(该值等于前面成员字节数和)必须是自己大小的整数倍;确保每个成员都落在一个内存块中。
  3. 到了最后一个成员,补齐字节要满足整个结构体的大小必须是内部最宽数据类型长度的整数倍;这是为了保证整个内存的数据之间也是对齐的(便于变量内存分配时满足第1点)。

代码示例:



//内部最宽8字节
struct a
{
    short a;
    char b;
    long long c;
};
//内部最宽4字节
struct b
{
    short a;
    char b;
    int c;
};
//内部最宽2字节
struct c
{
    short a;
    char b;
    short c;
};
//内部最宽2字节,末端补齐
struct d
{
    short a;
    char b;
    short c;
    char d;
};
//内部最宽1字节
struct e
{
    char a;
    char b;
    char c;
};
int main () {
    struct a a;
    struct b b;
    struct c c;
    struct d d;
    struct e e;
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(b));
    printf("%d\n", sizeof(c));
    printf("%d\n", sizeof(d));
    printf("%d\n", sizeof(e));
    return 0;
}

 输出:

16
8
6
8
3

 2.数据对齐

        内存对齐是为了CPU能一次访问到所需的变量(数据),数据对齐的目的除了这一点之外,还有的就是确保各个类型的数据能刚好存满。例如,有一个容器,有几种不同直径的小球,假设小球A能刚好存满于这个容器,那么这个小球的直径是与容器体积“对齐的”,否则,必然有多余控件不能再放一个小球;假设这几种小球各有任意个,放到容器都能刚好存满,那么这几种小球直径和容器体积是“对齐的”。事实上,这些小球的直径代表着CPU一次访问内存的大小。

ps:想法可能与实际情况有出入,遇到再修改说明。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值