版权声明:本文为博主原创文章,未经博主允许不得转载。 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)和结构体中最长数据类型长度中较小的那个。有效对齐值也叫对齐单位。
了解了上面的概念后,我们现在可以来看看内存对齐需要遵循的规则:
-
结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。
-
结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。