c/c++内存对齐

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22054285/article/details/87875586

内存对齐

什么是内存对齐

首先,举个例子,大家看看如下的程序中的结构体应该占用多大的内存。

#include <iostream>

using namespace std;

#pragma pack(1)
typedef struct
{
    char a ; 
    int b;
}A;
#pragma pack()

typedef struct
{
    char a;
    int b;
}B;

int main(int argc, char ** argv)
{
    cout << sizeof(A) << endl;
    cout << sizeof(B) << endl;
    return 0;
}	

大家有兴趣可以自己运行,没有采用强制对齐的结构体B的大小是8字节;

为何要进行内存对齐

尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度。

测试不对齐访问与对齐访问的差异

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>

using namespace std;

long GetTime() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    long tt = tv.tv_sec * 1000 + tv.tv_usec / 1000 ;
    return tt;
}
 
int main(int argc, char ** argv)
{
    char buf[512];
    int tmp = 0;
    int count = 100000000;
 
    memset(buf, sizeof(buf), 0);
    long t1 = GetTime();
    for (int i=0; i<count; ++i)
    {
        for (int j=1;j<(sizeof(buf)-4);j+=4)
        {
            tmp = *(int*)&buf[j];
            tmp++;
            *(int*)&buf[j] = tmp;
        }
    }
    long t2 = GetTime();
    printf("use time : %ld\n", t2 - t1);
 
    tmp = 0;
    memset(buf, sizeof(buf), 0);
    t1 = GetTime();
    for (int i=0; i<count; ++i)
    {
        for (int j=2;j<(sizeof(buf)-4);j+=4)
        {
            tmp = *(int*)&buf[j];
            tmp++;
            *(int*)&buf[j] = tmp;
        }
    }
    t2 = GetTime();
    printf("use time : %ld\n", t2 - t1);
 
    tmp = 0;
    memset(buf, sizeof(buf), 0);
    t1 = GetTime();
    for (int i=0; i<count; ++i)
    {
        for (int j=3;j<(sizeof(buf)-4);j+=4)
        {
            tmp = *(int*)&buf[j];
            tmp++;
            *(int*)&buf[j] = tmp;
        }
    }
    t2 = GetTime();
    printf("use time : %ld\n", t2 - t1);
 
    tmp = 0;
    memset(buf, sizeof(buf), 0);
    t1 = GetTime();
    for (int i=0; i<count; ++i)
    {
        for (int j=0; j<(sizeof(buf)-4); j+=4)
        {
            tmp = *(int*)&buf[j];
            tmp++;
            *(int*)&buf[j] = tmp;
        }
    }
    t2 = GetTime();
    printf("use time : %ld\n", t2 - t1);

    return 0;
}

然并卵,执行后是这样

use time : 42373
use time : 43083
use time : 42178
use time : 43036	

没看出差异,回头还得仔细分析下。

内存对齐规则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。gcc中默认#pragma pack(4),可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这一系数。

有效对其值:是给定值#pragma pack(n)和结构体中最长数据类型长度中较小的那个。有效对齐值也叫对齐单位。

了解了上面的概念后,我们现在可以来看看内存对齐需要遵循的规则:

  1. 结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。

  2. 结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

猜你喜欢

转载自blog.csdn.net/qq_22054285/article/details/87875586