什么是 uint_fast32_t,为什么要使用它来代替常规的 int 和 uint32_t?

Posted

技术标签:

【中文标题】什么是 uint_fast32_t,为什么要使用它来代替常规的 int 和 uint32_t?【英文标题】:What is uint_fast32_t and why should it be used instead of the regular int and uint32_t? 【发布时间】:2012-01-20 00:04:21 【问题描述】:

所以typedef:ed 原始数据类型的原因是为了抽象低级表示并使其更容易理解(uint64_t 而不是long long 类型,即 8 个字节)。

但是,uint_fast32_tuint32_t 具有相同的 typedef。使用“快速”版本会使程序更快吗?

【问题讨论】:

long long 可能不是 8 个字节,可能有一个 long long 1 个字节(如果 CHAR_BIT 至少为 64)或 3738383 个字节。 uint64_t 也可以是 1、2、4 或 8 字节,CHAR_BIT 必须是 64、3、16 或 8。 【参考方案1】: int 在某些平台上可能只有 16 位。这可能不足以满足您的应用需求。 uint32_t 不保证存在。这是一个可选的typedef,如果它具有正好为 32 位的无符号整数类型,则实现必须提供它。例如,有些有 9 位字节,因此它们没有 uint32_tuint_fast32_t 清楚地说明了您的意图:它是一种至少 32 位的类型,从性能的角度来看是最好的。 uint_fast32_t 实际上可能是 64 位长。这取决于实施。

...uint_fast32_tuint32_t 具有相同的 typedef ...

你看到的不是标准。这是一个特定的实现(黑莓)。所以你不能从那里推断uint_fast32_t总是和uint32_t一样。

另见:

Exotic architectures the standards committees care about.

My opinion-based pragmatic view of integer types in C and C++.

【讨论】:

好答案。为了完整起见,也可以指出与uint_least32_t 的区别,这与uint_fast32_t 相同,只是它更倾向于较小的存储而不是速度。 为什么宽度至少为 32 位的最快整数会大于 32 位?我一直认为,如果位越少,CPU 必须处理的位就会越少,从而更快。我在这里错过了什么? @ShaneHsu:假设一个 64 位 CPU 将有一个 64 位的加法器,它在一个周期内对 64 位数字求和。如果您只想处理 32 位数字也没关系,它不会比一个周期快。现在,虽然 x86/amd64 上不是这样,但 32 位整数可能甚至无法寻址。在这种情况下,处理它们需要额外的操作来从例如 64 位对齐的单元中提取 32 位。另请参阅链接的问题。编写 C++ 标准是为了使它可以在具有 37 位字的机器上工作......所以根本没有 32 位类型。【参考方案2】:

区别在于它们的准确性和可用性。

doc 这里说:

宽度正好分别为8、16、32和64位的无符号整数类型(仅在实现直接支持该类型时提供):

uint8_t
uint16_t
uint32_t
uint64_t

最快的无符号无符号整数类型,宽度至少分别为 8、16、32 和 64 位

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

所以区别非常明显,uint32_t 是具有完全 32 位的类型,并且实现应该提供它只有它具有类型恰好 32位,然后它可以将该类型定义为uint32_t。这意味着,uint32_t 可能可用也可能不可用

另一方面,uint_fast32_t 是一种至少 32 位的类型,这也意味着,如果实现可以将uint32_t 类型定义为uint_fast32_t if 它提供uint32_t。如果它不提供uint32_t,那么uint_fast32_t 可以是至少具有32 位的任何类型的typedef。

【讨论】:

但是,例如 uint_fast32_t 比 uint32_t 快的原因是什么?为什么它更快? @PravasiMeet:并非所有整数都以相同的方式访问。有些比其他更容易访问。更简单意味着更少的计算,更直接,从而导致更快的访问。现在uint32_t 在所有系统上都是 32 位的(如果存在的话),与具有 64 位的系统相比,这可能不会更快。 uint_fast32_t 另一方面至少 32位,甚至可以是64位。 @Destructor:在某些处理器上,如果变量存储在更长的寄存器中,编译器可能必须添加额外的代码来删除任何额外的位。例如,如果 uint16_t x; 存储在 ARM7-TDMI 上的 32 位寄存器中,则代码 x++; 可能需要评估为 x=((x+1)<<16)>>16);。在该平台的编译器上,uint_fast16_t 很可能被定义为 uint32_t 的同义词以避免这种情况。 为什么[u]int_(fast|least)N_t 不是可选的?当然不是标准要求所有架构都支持至少 64 位的原始类型?然而stdint.h 的措辞暗示他们必须这样做。我觉得奇怪的是,自 1999 年以来,在 64 位计算成为主流之前的几年,我们一直在执行这一点——更不用说落后于嵌入式架构(在许多情况下仍然是当前的)。这对我来说似乎是一个很大的疏忽。 @underscore_d:没有特别的原因,例如,该标准不适用于具有 16 字节数据 RAM 和 256 条指令空间的 PIC12 实现。这样的实现需要拒绝很多程序,但这不应该阻止它以既定的方式表现它可以满足需求的程序。【参考方案3】:

当您在您的程序中#include inttypes.h 时,您可以使用许多不同的方式来表示整数。

uint_fast*_t 类型只是定义了表示给定位数的最快类型。

这样想:你定义了一个short类型的变量,并在程序中多次使用它,这是完全有效的。但是,您正在使用的系统可能会更快地使用int 类型的值。通过将变量定义为uint_fast*t 类型,计算机只需选择它可以使用的最有效的表示。

如果这些表示之间没有区别,那么系统会选择它想要的任何一个,并始终一致地使用它。

【讨论】:

为什么是 inttypes.h 而不是 stdint.h?似乎 inttypes.h 只包含各种稍微有用的绒毛,加上 stdint.h 的包含? @underscore_d 我知道区别。但是,无论应用领域如何,谁在专业程序中使用 stdio.h? @Lundin 我不知道他们是谁,也不知道他们是否存在!我只是认为提供一个详细说明“稍微有用的绒毛”是什么的链接可能很有用;-) 也许它会帮助人们意识到您是对的,而他们不需要需要它.【参考方案4】:

请注意,快速版本可能大于 32 位。虽然快速 int 可以很好地适合寄存器并对齐等:但是,它将使用更多内存。如果你有大量的这些数组,你的程序会因为更多的内存缓存命中和带宽而变慢。

我认为现代 CPUS 不会从 fast_int32 中受益,因为通常在加载指令期间可能会发生 32 位到 64 位的符号扩展,并且存在更快的“本机”整数格式的想法是老式的。

【讨论】:

以上是关于什么是 uint_fast32_t,为什么要使用它来代替常规的 int 和 uint32_t?的主要内容,如果未能解决你的问题,请参考以下文章

如何命名一组标志?

GPIOx->BSRR = (((uint32_t)0x01) << pinpos);

int32,int,int32_t,int8和int8_t之间的区别

uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结

当int32_t是扩展整数类型且int是32位补码标准整数类型时,(INT32_MIN + 1)是什么

uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型 - 大总结,看完全明白了