在内存池分配器中使用uintptr_t是否安全且具备可移植性?
关于C语言内存池分配器中
uintptr_t的可移植性问题 我用C语言实现了一个简易内存池(Arena)分配器,在实现对齐分配逻辑时对uintptr_t的使用存在疑问。
内存池头文件
#ifndef ARENA_H #define ARENA_H #include <stddef.h> struct Arena; /* Returns a new arena allocator with a capacity of SIZE */ struct Arena *arena_new(size_t size); /* Allocates SIZE bytes of memory from ARENA aligned with a default alignment set to `__alignof__(max_align_t)`. */ void *arena_alloc(struct Arena *arena, size_t size); /* Allocates SIZE bytes of memory from ARENA with no alignment */ void *arena_alloc_packed(struct Arena *arena, size_t size); /* Allocates SIZE bytes of memory from ARENA aligned on ALIGN. */ void *arena_alloc_align(struct Arena *arena, size_t size, size_t align); /* Free all memory allocated with ARENA */ void arena_free(struct Arena *arena); #endif /* ARENA_H */
arena_alloc_align实现代码
void *arena_alloc_align(struct Arena *arena, size_t size, size_t align) { assert((align & 1) == 0 && "aligment must be a power of two"); uintptr_t curr_addr = (uintptr_t)arena->mem_block + arena->cursor; size_t padding = 0; if (align > 0 && !IS_ALIGNED(curr_addr, align)) padding = align - (curr_addr & (align - 1)); if(arena->cursor + padding + size > arena->capacity) return NULL; arena->cursor = padding + size; return (void *)curr_addr + padding; }
我的疑问如下:
uintptr_t是否可以安全使用?是否具备可移植性?- 因了解到该类型为C标准中的可选类型,是否存在部分编译器未实现的情况?
- 若存在,有哪些C标准规定的非可选类型可用来存储任意内存地址?
解答
1. uintptr_t的安全性与可移植性
uintptr_t是C99标准<stdint.h>中定义的可选无符号整数类型,设计目的就是用来存储转换为整数的void*指针,标准保证:如果一个实现提供了uintptr_t,那么将void*转换为uintptr_t再转换回void*,得到的指针与原指针等价。- 在现代主流编译器(GCC、Clang、MSVC等)和通用平台(x86、x86_64、ARM等)上,
uintptr_t都是被支持的,使用它做地址对齐计算是安全且可移植的。
2. 未实现uintptr_t的场景
C标准确实没有强制要求所有实现都提供uintptr_t,这种情况仅出现在一些非常特殊的平台:比如古老的16位系统、内存模型不支持指针与整数双向转换的奇特架构。这类平台在当前的开发场景中几乎不会遇到。
3. 替代的非可选标准类型
如果需要兼容极少数不支持uintptr_t的极端场景,可以选择以下非可选类型:
unsigned long:C标准规定unsigned long的宽度至少为32位,在绝大多数平台上,它的宽度与指针宽度一致(32位系统为32位,64位系统为64位),足以容纳指针转换后的整数值。虽然标准没有严格保证这一点,但这是实际开发中最可靠的替代方案。size_t:这是C标准强制要求的非可选类型,用于表示对象的大小。通常size_t的宽度也与指针宽度匹配,因为对象的大小不可能超过系统的地址空间上限。同样,标准未严格保证,但实际场景中兼容性很好。
注意:不要使用signed long等有符号整数类型,指针转换为有符号整数可能会触发符号扩展,导致地址计算错误。
内容的提问来源于stack exchange,提问作者user30097526
相关产品推荐
相关产品推荐

