首页 > 代码库 > 字节对齐

字节对齐

字节对齐

1. X86结构是小端模式存储,既数据低位在低存储地址,数据高位在高存储地址。例如 short x = 0x3344; 假设x的地址为 0xBFFFF0F4,那么0xBFFFF0F4地址里面存储的是字节0x44, 0xBFFFF0F5地址里面存储的是字节0x33.
2. 为了使CPU能够跟快的访问内存,变量地址和变量长度有关联,即所谓地址对齐。4字节的int类型变量,其起始地址应位于4字节边界上,
即起始地址能够被4整除,也就是地址低2位为0. N字节对齐就满足:address &(N-1)== 0。N为2,4,8,16等2的幂次。讨论3字节对齐,5字节对齐没有什么意义;
3. 结构体内变量存储空间,需要看整个结构体内最大变量长度,及各个变量的位置。
struct {
   char  a;
   short b;
   char  c;
}s1;
sizeof(s1) = 6
aa 00 | bb bb | cc 00

struct {
   char  a;
   char  c;
   short b;
}s2;
sizeof(s2) = 4
aa cc | bb bb

struct {
   char  a;
   int b;
   char  c;
}s3;
sizeof(s3) = 12
aa 00 00 00| bb bb bb bb| cc 00 00 00 00

struct {
   char  a;
   char  c;
   int   b;
}s4;
sizeof(s4) = 8
aa cc 00 00 | bb bb bb bb


// 申请align_size字节对齐的存储空间
void *aligned_malloc(int size, int align_size) {
    // 可以多申请align_size个字节。其中align_size-1字节用来调整对齐,1字节用来记录和实际分配的起始地址的偏差值。
    void *tempPtr = malloc(size + align_size);               // tempPtr是实际分配地址   
    char offset = align_size - ((int)tempPtr % align_size);  // 和实际分配地址的偏差值,范围是 [1, align_size]
    char *alignedPtr = (char*)tempPtr + offset;              // tempPtr + offset得到align_size字节对齐的地址空间
    alignedPtr[-1] = offset;                                 // 记录偏移值在前一个地址字节上
    return (void*)alignedPtr;
}

// 释放aligned_malloc函数申请到的存储空间
void aligned_free(void *ptr) {
    char offset = ((char*)ptr)[-1];   // 得到和实际分配地址的偏差值
    free((char*)ptr - offset);        // 得到实际地址
}

 0xzz zz zz zz ... oo vv vv vv ... vv
   |                         |    |
tmpPtr                  |    alignedPtr,函数返回值  
                      存储offset  
char *alignedPtr = (char*)tempPtr + offset;
char *tempPtr = (char *)alignedPtr - offset;

字节对齐