在基本池的实现中我有这样的东西(我将简化代码以使其更清晰)
struct unit_header{
struct unit_header* next, prev;
};
int number_of_units = 10
int unit_size = 5;
int full_block = number_of_units*(unit_size+sizeof(struct unit_header));
void* p_mem_full_block = malloc(full_block);
//iterate all units of mem_full_block
for (int i = 0; i< number_of_units; i++){
//pointer to each unit
struct unit_header* p_units = (struct unit_header*)((char*)p_mem_full_block + i*(unit_size+sizeof(struct unit_header)));
//.... some pointers stuff....
}
我知道这部分(下面)用于遍历mem_block的所有单元......
i * (unit_size+sizeof(struct unit_header))
我没有得到这一部分:
(字符*)p_mem_full_block
装置。为什么我必须进行此char *转换?
答案 0 :(得分:1)
这是因为根据C标准你无法添加,减去void *
的任何内容;但是为char *
定义了加法和减法,它们按指定的字节数推进指针。
但是,除非-Wpointer-arith
或-Wpedantic
启用,否则GCC允许无效指针算法作为没有警告的扩展名。
此外,整个操作看起来不太方便,因为unit_header
结构的对齐要求可能与unit_size
的倍数不同。实际上,5的unit_size
将导致问题,并且在许多处理器上,这样的代码将编译但在运行时崩溃,因为指针(prev
,next
)未对齐,例如,实现可能需要一个可被4或8整除的地址,而代码将允许其间的任何数字。但是,x86本身通常并不关心错误的对齐。
即。 两种指针类型之间的转换会产生错误对齐的结果根据C11具有未定义的行为。