是否有理由在跨平台代码中使用C ++ 11的std :: int_fast32_t或std :: int_fast16_t over int?

时间:2016-03-22 17:34:34

标签: c++ c++11 std

在C ++ 11中,我们提供了固定宽度的整数类型,例如std::int32_tstd::int64_t,它们是可选的,因此不是编写跨平台代码的最佳选择。但是,我们还为这些类型提供了非可选的变体:例如"快速"变体,例如std::int_fast32_tstd::int_fast64_t,以及"最小尺寸"变体,例如std::int_least32_t,两者的大小至少是指定的位数。

我正在处理的代码是基于C ++ 11的跨平台库的一部分,它支持在最流行的Unix / Windows / Mac编译器上进行编译。现在出现的一个问题是,如果用C ++ 11固定宽度整数类型替换代码中的现有整数类型是否有优势。

使用std::int16_tstd::int32_t等变量的缺点是缺乏可用的保证,因为只有在实现直接支持该类型时才提供它们(根据http://en.cppreference.com/w/cpp/types/integer })。

但是,由于int至少为16位且16位对于代码中使用的整数来说足够大,std::int_fast16_t对int的用法如何呢?以int替换所有std::int_fast16_t类型以及unsigned intstd::uint_fast16_t方式替换所有int类型是否有益,或者这是不必要的?

理论上,如果知道所有支持的平台和编译器都具有至少32位大小的std::int_fast32_t,那么分别用std::uint_fast32_tGET替换它们是否有意义?

2 个答案:

答案 0 :(得分:23)

当前计算机和编译器上的

int可以是16位,32位甚至64位。在未来,它可能会更大(例如,128位)。

如果您的代码没问题,请使用它。

如果您的代码仅经过测试并使用32位整数,请考虑使用int32_t。然后代码将在编译时失败,而不是在没有32位整数的系统上运行时运行时(这在今天非常罕见)。

int_fast32_t是你需要至少32位的时候,但是你非常关心性能。在硬件上,32位整数作为64位整数加载,然后在繁琐的过程中位移回到32位整数,int_fast_32_t可能是64位整数。这样做的代价是,在不起眼的平台上,您的代码行为非常不同。

如果你没有在这样的平台上进行测试,我会反对它。

在构建时间中断事情通常比在运行时休息更好。如果您的代码实际上是在需要这些功能的某个不起眼的处理器上运行的,那么然后就可以解决它。适用“你可能不需要它”的规则。

保守,在未经测试的硬件上生成早期错误,并且当您需要移植到所述硬件时,需要进行可靠的工作和测试。

简而言之:

当且仅当您在int大小不同的平台上测试您的代码(并将继续测试)时,使用int_fast##_t并且您已经证明性能改进是值得未来的维护。

使用常见int##_t大小的##意味着您的代码无法在尚未对其进行测试的平台上进行编译。这很好;未经测试的代码不可靠,不可靠的代码通常比无用的差。

在不使用int32_t和使用int的情况下,您的代码有时会有int个32,有时是64个(理论上更多),有时候{{}如果你愿意在每个int中测试并支持每一个这样的情况,那就去吧。

请注意,int的数组可能存在缓存问题:它们可能不合理地大。例如,int_fast##_t可以是64位。一个数千或数百万的阵列可以单独快速使用,但是由它们的批量导致的缓存未命中可能使它们整体变慢;事情变得缓慢存储的风险也在增加。

在这些情况下,

int_fast16_t会更快。

同样适用于网络传输和文件存储数据,除了网络/文件数据通常必须遵循稳定的编译器/硬件更改格式这一明显问题之外。然而,这是一个不同的问题。

但是,使用固定宽度整数类型时,必须特别注意int,long等仍具有与之前相同的宽度。整数提升仍然基于int的大小发生,这取决于您使用的编译器。代码中的整数将是int类型,具有关联的宽度。如果使用其他编译器编译代码,这可能会导致不必要的行为。有关更多详细信息:https://stackoverflow.com/a/13424208/3144964

答案 1 :(得分:1)

我刚刚意识到OP只询问int_fast##_t而不是int##_t,因为后者是可选的。但是,我会保留答案,它可以帮助某人。

我会添加一些东西。固定大小的整数对于构建其他语言的API非常重要(甚至是必须的)。例如,当你想要pInvoke函数并在.NET托管代码的本机C ++ DLL中将数据传递给它们时,就是一个例子。在.NET中,int保证是固定大小(我认为它是32位)。因此,如果您在C ++中使用int并且它被认为是64位而不是32位,则可能会导致问题并减少包装结构的序列。