intXX_t 和 int_fastXX_t 有啥区别?

Posted

技术标签:

【中文标题】intXX_t 和 int_fastXX_t 有啥区别?【英文标题】:What is the difference between intXX_t and int_fastXX_t?intXX_t 和 int_fastXX_t 有什么区别? 【发布时间】:2012-03-03 14:49:14 【问题描述】:

我最近发现了标准最快类型的存在,主要是int_fast32_t和int_fast64_t。

我总是被告知,为了在主流架构上正常使用,最好使用经典的 intlong,它们应该始终适合处理器的默认读取能力等等避免无用的数字转换。

在 C99 标准中,它在 §7.18.1.3p2 中说:

“typedef 名称 int_fastN_t 指定最快的有符号整数类型,宽度至少为 N。typedef 名称 uint_fastN_t 指定最快的无符号整数类型,宽度至少为 N。”

在 §7.18.1.3p1 中也有一段引用:

“指定的类型不能保证在所有用途中都是最快的;如果实现没有明确的理由选择一种类型而不是另一种,它只会选择一些满足符号和宽度要求的整数类型。”

我不清楚 fastest 的真正含义。我不明白什么时候应该使用这种类型,什么时候不应该使用。

我对此进行了一些谷歌搜索,发现一些 open source projects 已经将它们的一些功能更改为它,但不是全部。他们并没有真正解释为什么他们改变了一部分,并且了一部分,他们的代码。

你知道当 int_fastXX_t 真的 比经典的快时的具体情况/用法是什么?

【问题讨论】:

+1。我一直在想这个问题,C rationale 对这个话题很安静。 【参考方案1】:

Gnu libc defines int,uint_fast16,32_t 在为 64 位 CPU 编译时为 64 位,否则为 32 位。在 Intel 和 AMD 64 位 x86 CPU 上对 64 位整数的操作比对 32 位整数的相同操作要快。

【讨论】:

是的,但int 在这样的机器上不应该是 64 位吗? 不,int 可以小到 16 位,它的大小通常取决于编译器而不是平台。这可能是 16 位到 32 位转换的产物。 您的“更快”链接是比较 32 位和 64 位 CPU 模式以执行某些复杂任务,而不是比较同一 CPU 下 32 位和 64 位整数的性能模式。【参考方案2】:

IMO 他们毫无意义。

编译器并不关心你如何称呼一个类型,只关心它的大小和适用于它的规则。因此,如果 int、in32_t 和 int_fast32_t 在您的平台上都是 32 位的,那么它们几乎肯定都会执行相同的操作。

理论上说,语言的实现者应该根据他们的硬件上最快的东西来选择,但标准的编写者从来没有对最快的定义做出明确的定义。再加上平台维护者不愿意更改此类类型的定义(因为这将是 ABI 中断),并且定义最终在平台生命的开始时被任意选择(或从其他平台继承的 C 库是移植自),再也没有碰过。

如果您处于微优化级别,您认为可变大小可能会产生显着差异,请在 您的 处理器上使用 您的 代码对不同选项进行基准测试。否则不要担心。 “快速”类型不会添加任何有用的 IMO。

【讨论】:

如果标准允许int_fastN_t 类型具有不确定的上限,那将允许一些有用的优化,否则这些优化将不可用。在某些平台上,对存储在寄存器中的int32_t 的操作将比对同样存储的int16_t 的操作快,但对int16_t[] 的操作通常比对int32_t 的操作快。让int_fast16_t 以 16 位或 32 位的方式表现非确定性可以让编译器在这两种情况下实现更快的行为。【参考方案3】:

除了 int32_tint16_t 甚至不存在的奇异硬件之外,可能不会有任何区别。

在这种情况下,您可以使用int_least16_t 来获取可以包含 16 位的最小类型。如果您想节省空间,这可能很重要。

另一方面,使用int_fast16_t 可能会得到另一种类型,大于int_least16_t,但对于“典型”整数使用可能更快。实施必须考虑什么更快,什么是典型的。也许这对于某些特殊用途的硬件来说是显而易见的?

在大多数常见机器上,这些 16 位类型都将是 short 的 typedef,您不必费心。

【讨论】:

【参考方案4】:

在 C99 标准中,7.18.1.3 最快的最小宽度整数类型。

(7.18.1.3p1) “以下每种类型都指定了一个整数类型,通常是最快的225) 在所有至少具有指定宽度的整数类型中进行操作。”

225) “指定的类型不能保证在所有用途中都是最快的;如果实现没有明确的理由选择一种类型而不是另一种,它只会选择一些满足符号和宽度要求的整数类型。”

(7.18.1.3p2) "typedef 名称 int_fastN_t 指定最快的有符号整数类型,宽度至少为 N。typedef 名称 uint_fastN_t 指定最快的无符号整数 宽度至少为 N 的类型。”

int_fastN_tuint_fastN_t 类型对应于精确宽度整数类型 intN_tuintN_t。该实现保证它们至少占用N 位,但如果它可以使用更大的类型执行优化,则该实现可以占用更多位;它只是保证它们至少占用N 位。

例如,在 32 位机器上,uint_fast16_t 可以定义为 unsigned int 而不是 unsigned short,因为使用机器字长类型会更有效。

它们存在的另一个原因是精确宽度整数类型在 C 中是可选的,但最快的最小宽度整数类型和最小宽度整数类型(int_leastN_tuint_leastN_t)是必需的。

【讨论】:

这个不多解释。 “在 32 位机器上,uint_fast16_t 可以定义为 unsigned int”——是的,但是您可以直接使用普通的旧 unsigned int,因为它是本机整数宽度,并且标准保证它至少为 16位宽。同样,long 满足与int_fast32_t 大致相同的约束。 我已经阅读了基本原理,但这并没有说什么时候更快,具体用于什么用途?如果这真的每次都更快,为什么我们默认不使用它们? @larsmans uint_fast16_t 可以是 32 位机器中 unsigned int 和 64 位机器中 unsigned long 的别名。如果你打算在不同的机器上编译你的程序,在你的程序中使用unsigned int而不是uint_fast16_t将是不一样的。 @ouah 这是我的主要问题:我应该什么时候使用它?您有主要架构的示例用法吗? @Coren 我已经举了一个例子,你提到的问题是fast的定义。实现可以选择将快速算术运算优先于快速数组访问或相反。这就是我个人不使用这些类型的原因,我更喜欢选择适合我需要的精确整数类型。

以上是关于intXX_t 和 int_fastXX_t 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

发布和自动发布有啥区别,有啥方法可以创建用户定义的自动发布池? [复制]

Flutter 中 required 和 @required 有啥区别。它们之间有啥区别,我们啥时候需要使用它们?

oracle数据库11g和18c有啥区别? oracle sql developer和oracle apex与这些有啥关系?

Java 非堆内存和栈内存有啥区别?它们是不是相同,如果不同,它们之间有啥区别?

gradle和maven有啥用?分别有啥区别

VBS和JAVA和C++,有啥区别,有啥差距