前言:
1 若变量var要以2的N次幂对齐,以16 byte对齐为例,我们知道16= 0x10,那么16byte对齐的数值必须符合bit0~3均为0的规律,例如32=0x20,48=0x30等;
那么给定一个随机数,如何来达到bit0~3均为0的效果呢,var &~0x0f即可。同理,若需32byte对齐,先看32byte的十六进制对应是什么,32=0x20,bit0~bit4需要全为0。达到32byte对齐需要var &~0x1f才行。依次类推应该可以得出一个更通用的结论,若变量var需要以align byte(为2的N次幂)对齐,可以对当前数值var & ~(align -1)即能达到目的。
2 这里又有个问题,如何实现任意字节的对齐呢?假设数值366,我就是想让他变成199的整数倍,366 - 366%199 = 199就能达到目的。那么想让他变成199*2 =398呢,388+199 - 388%199 = 398就达到了目的。
3 cpu能访问的地址,一般都会要求至少4 byte对齐,所以没有2当中提到的可能性。
情景:
基于ANSI的malloc/free实现align_malloc/align_free函数,实现2的N次幂字节对齐,假设要求64byte对齐。实现该项的重点就是要保存base_addr,这样才能正确的free掉分配的区域,防止内存泄露。测试代码如下:
有一种特殊情形,就是当base_ptr本身已经对齐的情况下,仍然将base_ptr往上加align_bytes,已达到兼容性。
-
#include <stdio.h>
-
#include <stdlib.h>
-
-
-
void *align_ptr_malloc(int size,int align_bytes)
-
{
-
void *base_ptr =
NULL;
-
void *mem_ptr =
NULL;
-
-
-
base_ptr =
malloc(size + align_bytes);
//alloc alignbytes, rather than align_bytes-1, because we need to store offset
-
-
mem_ptr = (
void *)((
int)((
int *)base_ptr + align_bytes
-1) & ~(align_bytes
-1));
-
if(mem_ptr == base_ptr)
//base_ptr already align_bytes align
-
{
-
mem_ptr = base_ptr + align_bytes;
//force move it to one more alignbytes
-
}
-
*((
int *)mem_ptr
-1) = mem_ptr - base_ptr;
-
printf(
"offset is %d base prt %x mem_ptr %x\n",*((
int *)mem_ptr
-1),base_ptr,mem_ptr);
-
return mem_ptr;
-
}
-
-
-
void *align_ptr_free(void *ptr)
-
{
-
void *base_addr =
NULL;
-
printf(
"%x %x\n",ptr,*((
int *)ptr -
1));
-
base_addr = (
void *)(ptr- *((
int *)ptr
-1));
-
printf(
"ptr %x base_addr %x\n",ptr,base_addr);
-
free(base_addr);
-
}
-
-
-
void main()
-
{
-
void *ptr;
-
ptr = align_ptr_malloc(
1024,
64);
-
printf(
"ptr %x\n",ptr);
-
align_ptr_free(ptr);
-
}