你有一个操作系统,它有两个处理内存分配的函数:
void *malloc( int sz ) // allocates a memory block sz bytes long
void free( void *addr ) // frees a memory block starting at addr
// (previously allocated by malloc)
使用这些函数,实现以下2个函数:
void *malloc_aligned( int sz ) // allocates a memory block sz bytes long,
// aligned to an address divisible by 16
void free_aligned( void *addr ) // frees a memory block starting at addr
// (previously allocated by malloc_aligned)
在解决方案中有以下部分:
void * aligned_malloc(size_t size){
unsigned char *res=malloc(size+16);
unsigned char offest=16-((long)res%16);
我不明白的是:为什么我们需要使用 unsigned char 以及我们使用 16-((long)res%16);
的原因和效果以及目的是什么(long)res
在这种情况下?
最佳答案
您不能对“void *”进行指针运算,因为 void 没有大小。
对指针进行加法或减法时,总是以 sizeof(*p)
为单位进行。意思是——如果你给一个 int 指针加 1,它的值会增加 4(因为整数的大小是 4)。所以当你添加到一个 void 指针时,它应该增长一个 void 的大小。但是 void 没有大小。
但是,一些编译器愿意对void *
进行运算,他们将其视为char *
。使用这些编译器,您可以在不强制转换的情况下实现这些功能。但它不是标准的。
还有一点,并不是所有的运算符都适用于指针。加法和减法是,但乘法、除法和模数不是。因此,如果你想测试指针的低位,以了解它是否对齐,你可以将它转换为 long。
为什么长?假设 long 与指针一样大,这在 Linux 中是正确的,但在 Windows 中则不然。正确的类型是 uintptr_t。但是,如果您只对低位感兴趣,那么在转换时丢失高位也没关系。因此转换为 int 也会起作用。
关于地址的类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8777345/