【问题标题】:Proper use/includes for uint64_t in C++ [duplicate]在 C++ 中正确使用/包含 uint64_t [重复]
【发布时间】:2017-06-21 06:04:24
【问题描述】:

作为参考,我在 C++11 中编译。

我开始使用棋盘的位图表示作为以棋子为中心的方法来编写国际象棋引擎。似乎要使用的合适类型是 uint64_t ,但是,在网上搜索了很多之后,我有点不确定这里的“最佳实践”。

我开始为游戏板定义 .hpp 文件。 首先,我对不同代码似乎表现出的相似行为感到困惑。

#include <cstdint>
uint64_t board;

#include <cstdint>
std::uint64_t board;

两者都编译得很好。两者有什么区别?这个比那个好吗?

此外,我注意到我什至不需要包含 cstdint 就可以使用 uint64_t :

#include <iostream>
uint64_t board;

#include <iostream>
uint64_t std::board;

两者都编译得很好,就像上面的 2 个 cstdint 示例一样。因此,我很困惑 uint64_t 应该如何在 C++11 中使用,以及为什么所有这 4 个示例都做完全相同的事情。有人告诉我你想使用 cstdint ,但似乎 iostream 也提供了类型 def ?是否有“最佳/最安全”的特定方式(例如在命名空间冲突方面)?

【问题讨论】:

标签: c++ c++11


【解决方案1】:

&lt;cthing&gt; 标头作为其 C 遗产的一部分存在于 C++ 中。标准库不是重新发明轮子,而是重用 C 标准库的这些有用部分。现在,不同之处在于标题被重命名,并且它们必须在命名空间std 中定义它们的符号。他们还可能将它们添加到全局命名空间。请注意,他们可以这样做,而不是必须

这是因为这些标头(作为实现细节)将包含纯 C 标头 &lt;thing.h&gt; 并根据全局符号定义 std:: 符号。但这不是你可以依赖的。标准库的实现者有一天可能会决定不再那样做。如果您包含cstdint 并使用uint64_t 而不是std::uint64_t,您的程序可能会随机停止构建成功。

您拥有的唯一保证是std 命名空间中的符号将存在。所以你应该使用这些符号而不是全局符号。

现在,作为其自身实现的一部分,标准库可以在自身内部交叉包含自己的标头。您的版本很可能包含&lt;cstdint&gt; 以实现&lt;iostream&gt;。但同样,这是一个实现细节,而不是 C++ 标准的硬性要求。如果您的标准库版本发生更改,并且不再更改,您的代码将无法构建。

总而言之,让您的代码在不同的编译器和标准库实现之间尽可能可移植:

  1. 包括&lt;cstdint&gt; 并使用它在命名空间std 中定义的符号,这些符号必须存在。1
  2. 如果您需要任何符号,请在文档保证其存在的地方包含标题。不要依赖您偶然发现的实施细节。

(1) 从技术上讲,允许未定义固定宽度整数类型。这是因为标准知道并非所有平台都可以定义所有平台。实际上,您可以在现代台式机上使用它们。

【讨论】:

  • 回答的很好,很有帮助,谢谢。
  • IIRC,ISO C++ 仍然在全局命名空间中保留以 _t 结尾的类型名称,所以在我看来,他们不保证全局范围 uint64_fast64_t 更令人烦恼可以在纯 ISO C++ 中使用,而不必用std::uint_fast64_t 来弄乱东西。 (但不是std::intstd::long)。可移植代码不能安全地定义 uint_fast64_t 或任何其他 _t 类型本身。
  • @PeterCordes - 这是 POSIX 限制,而不是 C++ 或 C 限制。
  • 啊,谢谢,那不那么笨了。 (最终结果仍然很烦人,两全其美,IMO。但至少我们如何到达这里是有道理的。:/)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 2021-03-16
相关资源
最近更新 更多