【问题标题】:Difference between string.h and cstring?string.h 和 cstring 之间的区别?
【发布时间】:2012-01-12 22:15:13
【问题描述】:

string.hcstring 有什么区别?

哪个应该用于 C,哪个用于 C++(如果有的话)?

【问题讨论】:

  • C 和 C++ 不是同一种语言。既然你提到了cstring,我假设你的意思是 C++ 并删除了C 标签。
  • @BrianRoach mm.. 不完全是,我想比较一下,什么标题应该用于哪种语言。
  • 这没有意义,因为cstring 不能在 C 中使用。
  • 哦哇...谷歌搜索cstring真的改善了我的夜晚...
  • ¤ 我认为你在这里得到的所有答案在技术上都是不正确的。不过,我不在乎对他们投反对票。无论如何,[string.h] 将标识符放置在全局命名空间中,也可以将它们放置在标准命名空间中。而 [cstring] 将标识符放置在标准命名空间中,也可以将它们放置在全局命名空间中。你绝对不想要那种 [cstring] 行为,因为代码例如仅使用 strlen 可能与一个编译器一起工作,然后无法与另一个编译器一起编译。这是非常不愉快的惊喜。所以对于 C 和 C++,使用更安全的 [string.h]。干杯&hth.,

标签: c++ c


【解决方案1】:

在 C++ 中,您应该包含 cstring 作为标题,而在 c 中您应该包含 string.h 作为标题。

在 C++ 中

#include <cstring>

在 C 中

#include <string.h>

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

例如:
string.h 变为 cstring
stdio.h 变为 cstdio 等等...


由于其他答案为这个讨论增加了不同的维度,我觉得有必要参考神圣的标准来清除这一点。

根据 C++11 20.9.14.6 & 7

表 55 描述了标题 &lt;cstring&gt;
内容与标准 C 库头文件相同,但在 21.7 中指定更改为 memchr()

21.7 空终止序列实用程序 声明:

函数签名memchr(const void*, int, size_t)应替换为两个声明:

const void* memchr(const void* s, int c, size_t n);
void* memchr( void* s, int c, size_t n);

两者都应具有与原始声明相同的行为。

附录 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 中提供这些名称。 ——结束示例]

结论:

从以上参考资料:
我对我之前的建议进行了纠正,使用cstring 似乎没有明显的优势,而不是string.h,而正如@Alf 建议的那样,由于在使用cstring 作为标头时使用了不合格的函数名称,可能会出现一些编译问题。所以考虑到使用string.h 没有明显的缺点或使用cstring 的优点,我认为如果以适当的方式使用,两者都可以在C++ 中使用。

【讨论】:

  • @julio.alegria 不。不不不不。
  • 我的意思是,有可能(刚刚重新检查)
  • @julio.alegria:有可能并不代表它是正确的,这是你应该了解的 C++ 编程语言的一个重要特征。
  • @Als 等人:使用 [cstring] 作为 [string.h] 的 alternative 没有任何优点和一些严重的缺点,例如代码无法与其他编译器一起编译。所以在非此即彼的观点中,唯一明智的选择是[string.h]。我不确定将两者都包括在内是否有任何实际优势。可能是。但是只有 1,然后是 [string.h]。干杯,
  • @Nicol:我已经举了一个例子。但无论如何,使用任何 [string.h] 函数的代码,例如 strlen可能 使用 [cstring] 编译,并且可能会编译。因为在 C++11 中,[cstring] 可以随意乱扔全局命名空间。使用其他一些编译器和更清洁的 [cstring],则常规(我应该说习惯性吗?)调用无法编译。在 C++03 中,[cstring] 不允许以这种方式污染全局命名空间,这就是标题的整个点。然而,AFAIK 没有人实现这一点,所以它仍然完全没有意义......非常具有讽刺意味。
【解决方案2】:

string.hcstring

之间有细微的差别

Alf P. Steinbach 的答案(可以作为对所提问题的评论找到):

string.h 将标识符放置在全局命名空间中,也可以将它们放置在标准命名空间中。而cstring 将标识符放置在标准命名空间中,也可以将它们放置在全局命名空间中。您绝对不希望 cstring 行为,因为代码例如仅使用 strlen 可能适用于一个编译器,然后无法使用另一个编译器进行编译。这是非常不愉快的惊喜。所以对于 C 和 C++,使用更安全的string.h

【讨论】:

  • because code that e.g. uses just strlen may work fine with one compiler, then fail to compile with another compiler. 而且我发现在 Visual Studio 下编译而没有警告或错误的代码将在 GCC 中失败,因为某些 VS 标头会隐含包含 memcpy 之类的内容,而 GCC 不会。所以我看不出标题的不当使用是如何选择一个而不是另一个的理由。你不能保证自己什么。如果您包含c* 版本,那么您应该使用std:: 命名空间限定名称。如果你不是,那么你会得到你应得的。
  • @NicolBolas 你肯定比我有更多的专业知识。我认为使用 string.h 的好处只是为了安全起见。是的,这会将 string.h 的所有符号放在全局命名空间中,但 cstdio 也会发生同样的情况。那何必呢?
  • 看到bames53的回答了吗?
  • NicolBolas 只是现在...这对我来说似乎很奇怪。 @AlfP.Steinbach 怎么能这么肯定?
  • @Beginner:因为 ISO C++ 标准是这样说的。 barnes53 正确地写道,“标头的 C++ 版本实际上与 C 版本有一些差异。”。那是指 C++ 的 [string.h],而不是 [cstring] 和 [string.h] 之间的区别。干杯&hth.,
【解决方案3】:

在 C++ 中,C 语言头文件定义在命名空间 std 下。因此,如果您在 C++ 中使用这些标头,请使用 cstring 并消除 .h 。

【讨论】:

  • "在 C++ 中,C 语言的头文件是在命名空间 std 下定义的"
  • @Alf P. Steinbach,我认为 c 风格的库是在 C++ 的 std 命名空间下实现的。这个链接也这么说cplusplus.com/reference/clibrary
  • 您可以将该站点用作快速帮助,但不能作为参考。此外,您引用的链接说“库的每个元素都在 std 命名空间中定义”关于 cxxxx 标头,这几乎是正确的,但不是您认为的那样。 C++ 标准是参考。当前标准是 C++11。它并不便宜,但令人高兴的是,N3290 草案是相同的,并且在短时间内公开(如果你以后碰巧得到它,就像现在一样,那将是非法的,嘿嘿)。
【解决方案4】:

您可以将 string.h 用于 C 和 C++。

在 C++ 98 规范中,它定义了 cstring(在主规范中)和 string.h(在 Annex D.5,标准 C 库头文件中,为了兼容性),它们定义了一些与 string.h 相同的字符串函数C。而在现实世界中,所有 C++ 编译器都会提供 string.h 以兼容 C 代码。

所以,在我看来,由于 C++ 代码可能由 C 编码器维护,以及 C 的习惯,我更喜欢 string.h。它足够清晰、广为人知,并且更兼容(与 C 语言)。

顺便说一句,为了与 C 兼容,我在 C++ 98 规范中列出了 C++ 中的所有 18 个标头: assert.h、iso646.h、setjmp.h、stdio.h、wchar.h、ctype.h、limits.h、signal.h、stdlib.h、wctype.h、errno.h、locale.h、stdarg。 h、string.h、float.h、math.h、stddef.h、time.h

【讨论】:

  • "在 C++ 98 规范中,它只定义了 cstring",这是不正确的
  • 哦,是的。它在附件 D.5,标准 C 库头文件中提到。我会修复帖子。
【解决方案5】:

头文件的 C++ 版本实际上与 C 版本有一些差异。在 C 中,某些类型被实现为 typedef,但对于 C++,它会阻止模板专门化之类的东西作用于这些类型*,因此 C++ 将一些 C typedef 转换为实际类型。这意味着包含这些类型定义的 C 标头的 C++ 版本必须忽略它们。

C++ 也允许重载,因此 &lt;cstring&gt; 的 C++ 版本指定了一些 C 函数的重载,以允许函数在输入参数是指向非常量数据的指针时返回指向非常量数据的指针,而C 函数只接受并返回指向 const 的指针。

我也认为,但现在无法在标准中找到验证这一点的位,即 C++ 版本的标头必须将它们的名称放在 std 命名空间中,并且只将它们作为可选扩展名放在全局命名空间中.

* 比如下面的代码:

typedef int Foo;
template<typename T> struct Bar {};
template<> struct Bar<int> {};
template<> struct Bar<Foo> {};

导致以下错误:

main.cpp:7:19: error: redefinition of 'Bar<int>'
template<> struct Bar<Foo> {};
                  ^~~~~~~~
main.cpp:5:19: note: previous definition is here
template<> struct Bar<int> {};
                  ^
1 error generated.

在 C 中 wchar_t 是一个 typedef,因此这将阻止一个专门化适用于 wchar_t 但不适用于 wchar_t 使用的任何底层类型。 MSVC 2010 将 char32_t 和 char16_t 实现为 typedef 的事实使它们无法为这些类型提供 std::codecvt 特化。

【讨论】:

  • “防止模板专业化之类的东西处理这些类型”
  • 谢谢你的例子,现在我明白你的意思了意思。例如。在 C++ 中 wchar_t 是一个内置类型。关于全局命名空间的事情,请参阅我的回答。干杯,
【解决方案6】:

显然cstring 用于 C++,string.h 用于 C。

值得一提的是,如果您从string.h 切换到cstring,请记住在所有字符串函数调用之前添加std::

【讨论】:

    【解决方案7】:

    &lt;string.h&gt; 是 C Header,用于操作 NULL 终止字符数组 ~ 松散字符串。 &lt;string&gt; 是 C++ 提供的,它对字符串(字符)有更方便和高级的操作。 &lt;cstring&gt; 是 C++ 标头,提供与 C 类型字符串的向后组合性。

    &lt;cstring&gt;在函数中提供c字符串函数 方式类似 string1 = string2.c_str(); 还具有有用/基本/复古功能,如 strcpy()strlen() 提供 &lt;string.h&gt; C 风格,由 C++ 风格 copy() , size() .

    &lt;string.h&gt; 声明在

    全局命名空间

    同时, &lt;cstring&gt; 声明在

    标准(std)命名空间

    .

    【讨论】:

      【解决方案8】:

      在使用&lt;cstring&gt; 时,一些答案建议使用std:: 命名空间。但是,在没有 std 命名空间的情况下,代码仍然可以编译和运行。这是因为: &lt;cstring&gt; = "string.h" + &lt;functions defined in the std namespace&gt;

      这样做是为了保持与 C 的兼容性。 加入&lt;cstring&gt; 并同时调用memcpy()std::memcpy(),亲自尝试一下。

      【讨论】:

        猜你喜欢
        • 2015-08-21
        • 2012-03-04
        • 1970-01-01
        • 2012-10-01
        • 1970-01-01
        • 2021-12-25
        • 2020-05-10
        • 2014-09-20
        相关资源
        最近更新 更多