无符号整数转uintptr_t是否丢位?uintptr_t大小定义解析
类型转换的信息丢失问题
uintptr_t uint_to_uintptr(unsigned int n) { return (uintptr_t)n; } uintptr_t ulint_to_uintptr(unsigned long int n) { return (uintptr_t)n; } uintptr_t ullint_to_uintptr(unsigned long long int n) { return (uintptr_t)n; }
上述3个C语言类型转换操作中,哪一个不会造成信息(位)丢失?
C99标准规定:
以下类型表示一种无符号整数类型,具备如下特性:任何指向
void的有效指针均可转换为此类型,转换回指向void的指针后,结果与原指针相等:uintptr_t
但该标准并未指定此unsigned integer type的大小。这是否意味着它对应最宽无符号整数类型的最大值UINTMAX_MAX,还是仅等同于unsigned int?
解答
首先明确uintptr_t的核心定位:它是一个能完整容纳指针值的无符号整数类型,其宽度由目标平台的指针位宽决定(比如32位系统通常是32位,64位系统通常是64位)。C99标准只要求它满足"存储指针转换后的值、转换回指针能复原"这一核心特性,并没有强制规定它必须等于某一固定的整数类型。
三个转换的信息丢失情况
没有任何一个转换能在所有符合C99标准的平台上保证绝对不丢失信息,具体分析如下:
unsigned int→uintptr_t:只有当uintptr_t的位宽≥unsigned int时才不会丢失。主流平台都满足这一点,但标准并未禁止uintptr_t比unsigned int窄的极端情况(几乎不会出现),所以无法绝对保证。unsigned long→uintptr_t:在绝大多数主流平台上,unsigned long的位宽和uintptr_t一致(32位系统都是32位,64位系统都是64位),因此转换不会丢失信息。但标准没有强制要求两者等宽,只是常见实现会对齐。unsigned long long→uintptr_t:如果平台的uintptr_t位宽小于unsigned long long(比如32位系统中uintptr_t是32位,unsigned long long是64位),转换时高位会被截断,必然丢失信息;只有当uintptr_t是64位时,转换才安全。
uintptr_t的大小定位
它既不一定等于最宽无符号整数类型(uintmax_t),也不一定等同于unsigned int:
uintmax_t是标准定义的最宽无符号整数类型,能容纳任何其他无符号整数类型的值;而uintptr_t只需要满足存储指针值的需求,其位宽可能小于uintmax_t(比如某平台指针是32位,最宽整数是64位,此时uintptr_t是32位)。uintptr_t和unsigned int也没有必然等价关系:比如64位系统中unsigned int通常是32位,而uintptr_t是64位,两者明显不等同。
内容的提问来源于stack exchange,提问作者Parminder Singh
相关产品推荐
相关产品推荐

