在池的实现中从 void* 转换为 char*
Conversion from void* to char* in an implementation of pool
在一个基本池的实现中,我有这样的东西(我将简化代码以使其更清晰)
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))
我没明白这部分是什么:
(char*)p_mem_full_block
意思是。为什么我必须进行此 char* 转换?
这是因为根据C标准你不能对void *
进行任何加减运算;然而,加法和减法是为 char *
定义的,它们将指针前进给定的 字节数 .
但是,GCC 允许 void pointer 算法作为扩展而不会发出警告,除非由 -Wpointer-arith
或 -Wpedantic
等启用。
此外,整个操作看起来不太可移植,因为 unit_header
结构的对齐要求可能与 unit_size
的倍数不同。实际上,5 的 unit_size
会导致问题,并且在许多处理器上,此类代码会编译但在运行时崩溃,因为指针(prev
、next
)未对齐,例如实现可能需要一个可被 4 或 8 整除的地址,而代码将允许介于两者之间的任何数字。然而,x86 本身通常不太关心错误对齐。
即两种指针类型之间的转换产生的结果未正确对齐根据 C11 具有未定义的行为。
在一个基本池的实现中,我有这样的东西(我将简化代码以使其更清晰)
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))
我没明白这部分是什么:
(char*)p_mem_full_block
意思是。为什么我必须进行此 char* 转换?
这是因为根据C标准你不能对void *
进行任何加减运算;然而,加法和减法是为 char *
定义的,它们将指针前进给定的 字节数 .
但是,GCC 允许 void pointer 算法作为扩展而不会发出警告,除非由 -Wpointer-arith
或 -Wpedantic
等启用。
此外,整个操作看起来不太可移植,因为 unit_header
结构的对齐要求可能与 unit_size
的倍数不同。实际上,5 的 unit_size
会导致问题,并且在许多处理器上,此类代码会编译但在运行时崩溃,因为指针(prev
、next
)未对齐,例如实现可能需要一个可被 4 或 8 整除的地址,而代码将允许介于两者之间的任何数字。然而,x86 本身通常不太关心错误对齐。
即两种指针类型之间的转换产生的结果未正确对齐根据 C11 具有未定义的行为。