我刚刚完成了工作面试的一部分测试,有一个问题难住了我,甚至用谷歌作为参考。我想看看StackOverflow的工作人员可以做什么:

memset_16aligned函数需要传递给它一个16字节的对齐指针,否则它将崩溃。 a)如何分配1024字节的内存,并将其对齐到16字节的边界? b)在memset_16aligned执行后释放内存。

{    
   void *mem;
   void *ptr;

   // answer a) here

   memset_16aligned(ptr, 0, 1024);

   // answer b) here    
}

当前回答

在16字节计数vs 15字节计数的填充前面,为了获得N的对齐,您需要添加的实际数字是max(0,N-M),其中M是内存分配器的自然对齐(两者都是2的幂)。

由于任何分配器的最小内存对齐都是1字节,因此15=max(0,16-1)是一个保守的答案。然而,如果你知道你的内存分配器将给你32位整型对齐的地址(这是相当常见的),你可以使用12作为一个垫。

这对于本例来说并不重要,但对于具有12K RAM的嵌入式系统来说可能很重要,因为其中保存的每个int都很重要。

实现它的最好方法是,如果你真的想保存每一个字节,那么你可以把它作为宏,这样你就可以给它你的本机内存对齐。同样,这可能只对需要保存每个字节的嵌入式系统有用。

在下面的例子中,在大多数系统上,值1对于MEMORY_ALLOCATOR_NATIVE_ALIGNMENT来说是很好的,但是对于我们的32位对齐分配的理论嵌入式系统,以下可以节省一小部分宝贵的内存:

#define MEMORY_ALLOCATOR_NATIVE_ALIGNMENT    4
#define ALIGN_PAD2(N,M) (((N)>(M)) ? ((N)-(M)) : 0)
#define ALIGN_PAD(N) ALIGN_PAD2((N), MEMORY_ALLOCATOR_NATIVE_ALIGNMENT)

其他回答

您还可以尝试posix_memalign()(当然是在POSIX平台上)。

也许他们会满足于memalign的知识?正如乔纳森·莱弗勒(Jonathan Leffler)指出的,有两个更新的更可取的函数需要了解。

哦,弗罗林先我一步。但是,如果您阅读了我链接到的手册页,您很可能会理解前面的帖子提供的示例。

我很惊讶没有人投票赞成Shao的回答,据我所知,在标准C99中不可能做到要求的事情,因为将指针转换为整型在形式上是未定义的行为。(除了标准允许uintptr_t <-> void*的转换,但标准似乎不允许做uintptr_t值的任何操作,然后将其转换回来。)

long add;   
mem = (void*)malloc(1024 +15);
add = (long)mem;
add = add - (add % 16);//align to 16 byte boundary
ptr = (whatever*)(add);

你也可以添加一些16字节,然后通过添加指针下面的(16-mod)将原始ptr推到16位对齐:

main(){
void *mem1 = malloc(1024+16);
void *mem = ((char*)mem1)+1; // force misalign ( my computer always aligns)
printf ( " ptr = %p \n ", mem );
void *ptr = ((long)mem+16) & ~ 0x0F;
printf ( " aligned ptr = %p \n ", ptr );

printf (" ptr after adding diff mod %p (same as above ) ", (long)mem1 + (16 -((long)mem1%16)) );


free(mem1);
}