4

C 标准规定,在对其执行任何算术运算之前,小于int将被提升的整数操作数。int因此,对两个小于 的无符号值的操作int将使用有符号而不是无符号数学来执行。在确保使用无符号数学对 32 位操作数进行操作很重要的情况下(例如,将乘积可能超过 2⁶³ 的两个数字相乘)将由uint_fast32_t任何标准保证使用该类型以产生无符号语义而没有任何未定义行为? 如果没有,是否有任何其他无符号类型保证至少为 32 位且至少与 一样大int

4

2 回答 2

5

不,这不对。无论如何,我建议不要使用这些[u]int_fastN_t类型。在现实世界的系统中,它们被错误定义;例如,uint_fast32_t通常在 x86_64 上被定义为 64 位类型,尽管 64 位操作(加法、减法、逻辑运算)充其量与 32 位操作速度相同,而最坏的情况则慢得多(除法和加载/存储)因为你使用了两倍的缓存行)。

于 2014-03-14T05:21:44.597 回答
2

C 标准只需要int至少 16 位,并且没有对其宽度设置上限,因此uint_fast32_t可以比 更窄int,或相同宽度,或更宽。

例如,符合要求的实现可以为int64 位,而uint_fast32_ttypedef 为 32 位unsigned short。或者,相反,int可以是 16 位uint_fast32_t,并且顾名思义,必须至少为 32 位。

一个有趣的结果是:

uint_fast32_t x = UINT_FAST32_MAX;
uint_fast32_t y = UINT_FAST32_MAX;
x * y;

可能溢出,导致未定义的行为。例如,如果short是 32 位和int64 位,则uint_fast32_t可以是 typedef for ,在相乘之前unsigned short会提升为有符号整数;结果接近 2 64,太大而无法表示为int

POSIX 要求int并且unsigned int至少为 32 位,但即使对于 POSIX 兼容的实现,您的问题的答案也不会改变。uint_fast32_t并且int仍然可以分别是 32 位和 64 位,或者 64 位和 32 位。(后者意味着 64 位类型比 快int,这很奇怪,因为它int应该具有“架构建议的自然大小”,但这是允许的。)

在实践中,大多数编译器实现者倾向于尝试使用预定义类型覆盖 8、16、32 和 64 位整数,这可能只有int不超过 32 位。我见过的唯一不遵循这一点的编译器是用于 Cray 向量机的。(扩展整数类型可以解决这个问题,但我还没有看到一个编译器可以利用它。)

如果没有,是否有任何其他无符号类型保证至少为 32 位且至少与 一样大int

是的,unsigned longunsigned long long至少是 64 位。)

于 2014-03-14T06:50:00.337 回答