什么是 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_t
与 uint32_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_t
。
uint_fast32_t
清楚地说明了您的意图:它是一种至少 32 位的类型,从性能的角度来看是最好的。 uint_fast32_t
实际上可能是 64 位长。这取决于实施。
...
uint_fast32_t
与uint32_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 是什么数据类型 - 大总结,看完全明白了