&address + sizeof(type)和&address + 1有什么区别?

时间:2018-12-14 16:52:59

标签: c unix memory-management malloc mmap

我正在尝试重新编码malloc函数。
假设我们有一个像这样的结构:

typedef struct      s_block
{
    char            is_free;
    size_t          size;
    struct s_block  *next;
    void            *memory;
}                   t_block;

我用mmap分配了一个内存页面,并将其转换为一个大的t_block。
然后,我有1个块,大小为4064(4096-t_block的大小)。
例如,如果我用大小为12的malloc进行调用,这就是我要做的:

block->next = &block + 1 + size // Setting the next block
block->next->size = block->size - size - sizeof(t_block); // 4064 - 12 - 32
block->size = size; // 12
block->is_free = NOT_FREED;
block->memory = &block + 1;
block->next->memory = &(block->next) + 1;
block->next->next = NULL;
block->next->is_free = FREE;

当我使用+ 1或+ sizeof(t_block)时,我经常遇到问题。 那么,

有什么区别?
block->next = &block + 1 + size;

和:

block->next = &block + sizeof(t_block) + size;

2 个答案:

答案 0 :(得分:2)

假设block被声明为t_block *,并且您希望此块与下一个块之间有size个字节,那么您所期望的也不是。由于&block是指针的地址,因此在其上进行的任何指针算术运算都基于指针的大小而不是结构的大小。

您真正想要的是:

block->next = (t_block *)((char *)block + sizeof(t_block) + size);

首先将block强制转换为char *,对它执行的所有指针算法都对单个字节起作用,而不是结构大小的倍数。因此,我们从块的地址开始,将sizeof(t_block)个字节上移到用户内存的开头,然后再将size个字节上移到该内存的末尾以及下一个块的开头。

此外,由于结构的对齐要求,您需要确保正确对齐下一个块。您可以按照以下步骤进行操作:

size_t block_align = (sizeof(t_block) - (size % sizeof(t_block))) % sizeof(t_block);
block->next = (t_block *)((char *)block + sizeof(t_block) + block_align + size);

答案 1 :(得分:0)

((Type*)(p)) + n == ((char*)(p)) + sizeof(Type)*n

类型化指针上的算术运算(即实际上只是加/减)是根据指向类型(sizeof(char)定义为1)的大小来缩放的。