【问题标题】:<cstdint> vs <stdint.h><cstdint> 与 <stdint.h>
【发布时间】:2012-11-18 12:47:06
【问题描述】:

stdint.hcstdint 有什么区别?

它们都在 MSVC (Visual Studio 2010) 和 gcc-4.5.1 中可用。还都定义了intX_t/uintX_t 类型(其中X 是类型的字节大小)。

  • 如果两个标题中的基本原理相同(便携式类型),我必须做出哪些决定来决定其中一个?

stdint.h 定义了没有任何命名空间的每个类型,cstdint 类型位于 std 命名空间中。

  • 是否有任何理由将定义的类型包含或不包含到std 命名空间中?这两个标题有什么不同?

cstdint 没有文件扩展名并使用c 前缀,stdint.h 使用.h 扩展名。

  • 此标头的命名约定是什么? c 前缀表示这是一个 C 库? cstdint 中缺少文件扩展名是有原因的吗?

【问题讨论】:

标签: c++ stdint cstdint


【解决方案1】:

C++98 的初衷是你应该在 C++ 中使用&lt;cstdint&gt;,以避免污染全局命名空间(嗯,不是&lt;cstdint&gt;,这只是在 C++11 中添加的,但是 @一般为 987654323@ 标头)。

然而,实现仍然坚持将符号放入全局命名空间,C++11 批准了这种做法[*]。所以,你基本上有三个选择:

  • 使用&lt;cstdint&gt; 并完全限定您使用的每个整数类型,或者使用using std::int32_t; 等将其带入范围(烦人,因为冗长,但它是正确的方法,就像C++ 标准中的任何其他符号一样图书馆)
  • 使用&lt;stdint.h&gt;(有点不好,因为已弃用)
  • 使用&lt;cstdint&gt; 并假设您的实现会将符号放在全局命名空间中(非常糟糕,因为无法保证)。

在实践中,我怀疑大量烦人的代码使用最后一个选项,仅仅是因为在 &lt;cstdint&gt; 将符号放在全局命名空间中的实现中很容易意外地做到这一点。你应该尝试使用第一个。第二个有一个优点,即保证将东西放在全局命名空间中,而不是仅仅可能这样做。我认为这不是特别有用,但如果这是您的优先事项,它可能会节省一些打字时间。

还有第四个选项,#include &lt;cstdint&gt; 后跟 using namespace std;,这有时很有用,但有些地方不应该放 using namespace std;。不同的人会有不同的想法,这些地方在哪里,但是“在头文件的顶层”比“在cpp文件的顶层”差,这比“在有限范围内”差。有些人根本不写using namespace std;

[*] 这意味着允许 C++ 标准头文件将内容放在全局命名空间中,但不是必须的。因此,您必须避免与这些符号发生冲突,但您实际上不能使用它们,因为它们可能不存在。基本上,C++ 中的全局命名空间是一个雷区,尽量避免它。有人可能会争辩说,委员会已经通过实现批准了一种做法,这种做法几乎与在头文件的顶层粘贴 using namespace std; 一样有害——不同之处在于实现只对 C 标准库中的符号执行此操作,而 @ 987654334@ 也适用于仅限 C++ 的符号。 C 标准中有一个部分列出了为将来添加到标准中而保留的名称。将这些名称也视为保留在 C++ 全局命名空间中并不是一个完全愚蠢的想法,但这不是必需的。

【讨论】:

  • 剩下的唯一未解决的问题是关于头文件的命名约定,你知道这个话题吗?
  • @PaperBirdMaster:C++ 标准库头文件没有文件扩展名:&lt;iostream&gt;&lt;vector&gt;&lt;cstdlib&gt;,除了为 C 兼容性而包含的那些:&lt;stdint.h&gt;&lt;stdlib.h&gt; .是的,最初的c 表示&lt;cstdlib&gt; 是C++ 的C 标准头文件&lt;stdlib.h&gt; 的等价物,而不是像&lt;vector&gt; 那样对C++ 来说是全新的。有一个 C++ 头文件 &lt;complex&gt;,所以我们只希望未来的 C 版本不会引入标准头文件 &lt;omplex.h&gt;
  • @SteveJessop Erm,C99?
  • @JL2210 注意他说的是&lt;omplex.h&gt;,而不是&lt;complex.h&gt;。如果 C 添加了 &lt;omplex.h&gt;,则 C++ 等价物将是 &lt;complex&gt;
【解决方案2】:

包括cstdint 会在 std 命名空间中导入符号名称,可能在全局命名空间中。
包括stdint.h 会在全局命名空间中导入符号名称,可能在 std 命名空间中。

C 标准库的功能也在 C++ 标准库中提供,并且作为一般命名约定,它们在 C 标准库中的相应名称前加上 c。

在 C++ 中,您应该使用:

#include <cstdint>

并完全限定您与std:: 一起使用的符号名称
在 C 语言中,您应该使用:

#include <stdint.h>

附录 D(规范性)兼容性特性 [depr] 规定:

D.6 C 标准库头文件

1 为了与 C 标准库和 C Unicode TR 兼容,C++ 标准库提供了 25 个 C 标头,如表 151 所示。

其中包括:

&lt;assert.h&gt; &lt;float.h&gt; &lt;math.h&gt; &lt;stddef.h&gt; &lt;tgmath.h&gt; &lt;complex.h&gt; &lt;inttypes.h&gt; &lt;setjmp.h&gt; &lt;stdio.h&gt; &lt;time.h&gt; &lt;ctype.h&gt; &lt;iso646.h&gt; &lt;signal.h&gt; &lt;stdint.h&gt; &lt;uchar.h&gt; &lt;errno.h&gt; &lt;limits.h&gt; &lt;stdarg.h&gt; &lt;stdlib.h&gt; &lt;wchar.h&gt; &lt;fenv.h&gt; &lt;locale.h&gt; &lt;stdbool.h&gt; &lt;string.h&gt; &lt;wctype.h&gt;

还有,

2 每个 C 标头都有一个 name.h 形式的名称,其行为就像每个由相应 cname header 放置在标准库命名空间中的名称都放置在全局命名空间范围内一样。 未指定这些名称是否首先在命名空间 std 的命名空间范围 (3.3.6) 内声明或定义,然后通过显式 using 声明 (7.3.3) 注入全局命名空间范围。

3 [ 示例:标题&lt;cstdlib&gt; 确实在命名空间std 中提供了它的声明和定义。它还可以在全局命名空间中提供这些名称。标题&lt;stdlib.h&gt; 确实在全局命名空间中提供了相同的声明和定义,就像在 C 标准中一样。它还可以在命名空间 std 中提供这些名称。 ——结束示例]

【讨论】:

    【解决方案3】:
    1. cstdint 是 C++11 标头,stdint.h 是 C99 标头(C 和 C++ 是不同的语言!)

    2. MSVC 2008 既不包含 stdint.h 也不包含 cstdint

    3. cstdint 的实现大多只是简单的 #include &lt;stdint.h&gt;,并修复了一些命名空间/语言。

    【讨论】:

    • 3.是错的。 cstdint 需要将实现提升到命名空间 std
    • 1.也是错误的,stdint.h 在 C++ 标准的规范附录 D 中被定义为 C++ 库的一部分。
    • @chill,能否提供附件 D 的链接?这里en.cppreference.com/w/cpp/types/integer 声明是 C++11 头文件。
    • @hate-engine,我建议您在您的 C++ 标准副本中查找它。该 cppreference 页面未提及 stdint.h。毫无疑问,cstdint 是 C++ 标头。
    • 1. 的任何部分都不是错误的,只是综合起来看起来好像你在说stdint.h 不是 C++11 的一部分。实际上它是 C++11 所要求的。你可以说,“int 在 C++11 中;long 在 C99 中;C 和 C++ 是不同的语言!”,也没有任何部分是错误的。不过,我的示例甚至更具误导性,因为 C++11 部分引用 C99 来定义 stdint.hcstdint 的内容,但没有引用 C 来定义 int
    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2015-03-05
    • 2020-05-23
    相关资源
    最近更新 更多