如何不使用预处理指令生成适配size_t位数的无效地址十六进制值?
无需预处理指令生成平台相关的无效地址值
当然可以实现,核心思路是利用编译期类型大小计算自动适配32位/64位平台,完全不需要#ifdef这类预处理指令。以下是几种可靠的实现方式:
方法1:使用uintptr_t(推荐,跨平台兼容性最佳)
uintptr_t是C99标准定义的类型,保证其宽度与当前平台的指针宽度一致,需要包含头文件<stdint.h>:
#include <stdint.h> // 编译期自动计算:32位平台为0xaaaaaaaa,64位平台为0xaaaaaaaaaaaaaaaa const uintptr_t invalid_addr = (uintptr_t)(0xaaaaaaaaULL * (1ULL + (sizeof(uintptr_t) == 8 ? 0x100000000ULL : 0)));
原理:编译器在编译时会根据平台计算sizeof(uintptr_t)的值,三元运算符会被直接替换为常量,最终表达式会被优化为对应平台的目标值。
方法2:直接使用指针类型转换
如果不想引入<stdint.h>,可以直接基于void*类型构造:
// 同样编译期适配平台 void* const invalid_addr = (void*)((sizeof(void*) == 8) ? 0xaaaaaaaaaaaaaaaaULL : 0xaaaaaaaaUL);
原理:sizeof(void*)是编译期常量,编译器会自动选择对应的十六进制值进行强制转换。
方法3:利用位运算构造
通过位运算重复低32位的模式到高32位(仅适用于64位平台),同时兼容32位:
#include <stdint.h> const uintptr_t invalid_addr = (uintptr_t)(0xaaaaaaaaULL | (sizeof(uintptr_t) == 8 ? (0xaaaaaaaaULL << 32) : 0));
原理:64位平台下将0xaaaaaaaa左移32位后与原值按位或,得到0xaaaaaaaaaaaaaaaa;32位平台下左移操作被抵消,结果就是0xaaaaaaaa。
注意事项
- 以上所有实现中的表达式均为编译期常量,编译器会直接将其优化为对应平台的固定值,不会产生运行时开销。
- 若需兼容Windows 64位平台,避免使用
unsigned long(Windows下unsigned long为32位),优先选择uintptr_t或unsigned long long。
内容的提问来源于stack exchange,提问作者cleong
相关产品推荐
相关产品推荐

