地址的类型转换

标签 c casting

你有一个操作系统,它有两个处理内存分配的函数:

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/

相关文章:

c - 二维数组上的 memcpy

c# - 尝试将装箱的 int 转换为 byte

c++ - 将派生类型转换为基类型

c++ - 将指针指向它的第一个成员是非法的吗?

postgresql - 有没有更简洁的方法将查询结果转换为类型?

c - 初始化元素在 C 中不是常量

c - 在连接到服务器之前尝试编译客户端时出错

c - 从 C 程序中删除注释

c - sscanf - 带有可选/空格式说明符的解析帧

将 volatile 表达式的结果转换为 void