内存地址对齐

目录

一、基础知识

1、CPU位数(地址总线)

2、寄存器位宽

3、数据总线

二、地址对齐

三、示例代码

1、POSIX标准

2、GNU拓展特性

一、基础知识

1、CPU位数(地址总线)

        CPU 位数通常描述的是 CPU 地址总线的长度,即用于寻址内存的总线的宽度。

        在计算机系统中,地址总线用于传输 CPU 发出的内存地址信号,决定了 CPU 能够寻址的内存空间大小:

        (1)32 位 CPU 的寻址能力为 2^32,即能够寻址的内存空间大小为 4GB。

        (2)64 位 CPU 的寻址能力为 2^64,理论上能够寻址的内存空间极大,远超当前实际需求。

        64 位 CPU 相比于 32 位 CPU 具有更大的内存寻址空间和更高的数据处理能力,能够更好地支持大内存应用和处理大数据量的计算任务。

2、寄存器位宽

        寄存器是 CPU 中用来存储临时数据和执行指令的一种存储设备。寄存器位宽指的是一个寄存器能够存储的位数,也就是寄存器的大小。通常情况下,寄存器位宽与 CPU 的数据处理能力有关,比如一个64位CPU的通用寄存器通常是64位宽度,可以存储64位的数据。

        CPU 位数也决定了寄存器的位宽

        (1)32 位 CPU 的通用寄存器是 32 位宽度,一次能够处理 32 位(4 字节)的数据。

        (2)64 位 CPU 的通用寄存器是 64 位宽度,一次能够处理 64 位(8 字节)的数据。

3、数据总线

        数据总线是 CPU 与其他设备(如内存、外设)之间传输数据的总线,用于在各个部件之间传递数据。数据总线的宽度表示一次能够传输的数据位数,比如一个64位数据总线可以一次传输64位的数据。

        数据总线的长度可能与地址总线不同,目前 CPU 在设计的时候大多独立考虑。

        寄存器位宽决定了 CPU 内部处理数据的能力,而数据总线宽度影响了 CPU 与其他设备之间传输数据的效率和速度

二、地址对齐

        为了更好的说明,下面以 32 位 CPU 读取 int 变量为例。

        32 bit 的 CPU 每次可以读取 4 byte 的数据。CPU 在读取读取数据时会尽可能的减少 CPU 的读取操作的次数,例如,对于 4 byte 长度的 int 类型变量,最优的就是 CPU 一次读取就将该变量全部数据获取到。

        但实际情况可能并不如此,在内存不对齐的情况下,CPU 可能需要两次才可以完全读取该变量。

        所以,内存对齐的情况下,虽然浪费一定的空间,但是可以极大的提高 CPU 读取数据的效率。而且有些系统在不内存对齐的情况下,可能会崩溃。

        在linux下可以使用 printf("%p\n", &var); 查看变量的其实地址。进行内存对齐时,还需要考虑 CPU 的位数。

        对于非标准数据类型按下面的原则对齐:

        (1)数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。

        (2)联合 :按其包含的长度最大的数据类型对齐。

        (3)结构体:结构体中每个数据类型都要对齐。

三、示例代码

1、POSIX标准

        在 Linux 下,可以使用 posix_memalign() 函数在堆内申请内存对齐的变量。

int posix_memalign(void **memptr, size_t alignment, size_t size);

        其中,memptr 是一个指向指针的指针,用于存储分配的内存地址;alignment 表示所需对齐的字节数,必须是 2 的整数次幂;size 表示需要分配的字节数。

#include <stdio.h>
#include <stdlib.h>

int main() {
    void *ptr;
    size_t size = 32;
    size_t alignment = 16;

    // 分配对齐的内存
    int result = posix_memalign(&ptr, alignment, size);

    if (result != 0) {
        printf("内存分配失败\n");
        return -1;
    }

    printf("分配的内存地址: %p\n", ptr);
    free(ptr);

    return 0;
}

2、GNU拓展特性

        __attribute__ 是一个 GNU C/C++ 编译器的扩展特性,用于指定变量或函数的属性,包括对齐属性。通过在变量或函数声明时使用 __attribute__((aligned(n))) 可以指定对齐方式为 n 字节。这种方式适用于编译器支持 __attribute__ 特性的情况。

#include <stdio.h>

// 定义一个结构体并指定对齐属性为 16 字节
struct __attribute__((aligned(16))) AlignedStruct {
    int x;
    char y;
};
 
// 定义一个数组并指定对齐属性为 32 字节
int array[4] __attribute__((aligned(32)));

int main() {
    // 输出数组地址及大小
    printf("数组地址: %p\n", &array);
    printf("数组大小: %lu\n", sizeof(array));

    return 0;
}
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我要出家当道士

打赏是不可能,这辈子都不可能

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值