当前位置: 首页 > 知识库问答 >
问题:

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

皮承基
2023-03-14

在C 11中,我们提供了固定宽度的整数类型,如<code>std::int32_t,它们是可选的,因此对于编写跨平台代码不是最佳的。然而,我们也得到了类型的非可选变体:例如“快速”变体,例如<code>std::int_fast32_t,以及“最小大小”变体,如<code>std::int-least32_。

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

使用像<code>std::int16_t这样的变量的缺点是缺乏对它们可用的保证,因为只有在实现直接支持类型时才提供它们(根据http://en.cppreference.com/w/cpp/types/integer).

然而,由于<code>int</code>至少是16位,并且16位对于代码中使用的整数来说足够大,那幺<code>std::int_fast16_t</code>在int上的用法如何?用<code>std::int_fast16_t类型,用<code>std::uint_fast16_t替换所有<code>无符号int类型,这样做有好处吗?这是不必要的吗?

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

共有2个答案

鲜于峰
2023-03-14

我刚刚意识到,OP只是询问< code>int_fast##_t而不是< code>int##_t,因为后者是可选的。然而,我会保持答案跳跃它可能帮助某人。

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

胡浩瀚
2023-03-14

在当前计算机和编译器上,< code>int可以是16位、32位甚至64位。将来,它可能会更大(比如128位)。

如果您的代码可以接受,请使用它。

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

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

如果你不在这样的平台上测试,我建议你不要这么做。

在构建时中断通常比在运行时中断要好。如果您的代码实际上运行在某个需要这些特性的不知名的处理器上,那么就修复它。“你可能不需要它”的规则适用。

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

简而言之:

使用< code>int_fast##_t,当且仅当您已经在int大小不同的平台上测试了您的代码(并将继续测试它),并且您已经表明性能的提高值得未来的维护。

将<code>int##t

如果不使用< code>int32_t,而使用< code>int,您的代码有时会有32的< code>int,有时会有64的int(理论上更多),有时会有16的< code>int。如果您愿意在每一个这样的< code>int中测试和支持每一个这样的情况,那就去做吧。

请注意,int_fast##t数组可能存在缓存问题:它们可能太大。例如,int_fast16_t可以是64位。一个几千或几百万个的数组可以单独快速处理,但由于它们的大容量导致的缓存未命中可能会使它们整体速度变慢;而且,将东西交换到速度较慢的存储中的风险也在增加。

在这些情况下,< code>int_least##_t可以更快。

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

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

 类似资料:
  • 在我的Fedora 34环境(g)中,定义为: 如果表达式已经是右值,那么

  • 我在理解条件变量及其在互斥体中的使用时遇到了一些困难,我希望社区能帮助我。请注意,我来自win32背景,因此与CRITICAL_SECTION、HANDLE、SetEvent、WaitForMultipleObject等一起使用。 这是我第一次尝试使用C++11标准库进行并发操作,它是在这里找到的一个程序示例的修改版本。 关于这个的几个问题。 我读过“任何要等待std::condition_var

  • 令我惊讶的是,已经完成执行但尚未加入的C11std::thread对象仍然被视为活动执行线程。下面的代码示例说明了这一点(基于Xubuntu 13.03和G4.7.3构建)。有人知道C 11标准是否提供了一种检测std::thread对象是否仍在积极运行代码的方法吗?

  • 在“掌握C++17 STL”一书中,我看到iterator和const_iterator在一个类中实现,使用条件来减少代码重复 下面是我对简单数组类的实现(跳过数组类的大部分代码): 这段代码编译时没有错误,但iterator有点不可用: 给出错误: 我该如何使用那个迭代器呢?还是我应该从书上放弃这个想法呢?

  • 我有两个用例。 a.我想为两个线程同步对队列的访问。