string.h
和cstring
之间有什么区别?
哪一个应该用于C,哪一个用于C ++(如果有的话)?
答案 0 :(得分:20)
在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&amp; 7 :
表55描述了标题
<cstring>
内容与标准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所示。
其中包括:
<assert.h> <float.h> <math.h> <stddef.h> <tgmath.h>
<complex.h> <inttypes.h> <setjmp.h> <stdio.h> <time.h>
<ctype.h> <iso646.h> <signal.h> <stdint.h> <uchar.h>
<errno.h> <limits.h> <stdarg.h> <stdlib.h> <wchar.h>
<fenv.h> <locale.h> <stdbool.h> <string.h> <wctype.h>
继续,
2 每个C标头(每个标头都有
name.h
形式的名称,就好像每个名称放置在标准库名称空间中的相应cname header
放置在全局范围内命名空间范围。未指定这些名称是在名称空间std的名称空间作用域(3.3.6)中首先声明或定义的,然后通过显式使用声明(7.3.3)注入全局名称空间作用域。3 [示例:标题
<cstdlib>
确定在命名空间std中提供其声明和定义。它还可以在全局命名空间中提供这些名称。标头<stdlib.h>
确实在全局命名空间中提供相同的声明和定义,就像在C标准中一样。它还可以在命名空间std中提供这些名称。 - 例子]
从以上参考文献:
我在先前的建议中得到了纠正,使用cstring
而不是string.h
似乎没有明显的优势,而@Alf建议在使用{{{{}}时可能存在一些编译问题,因为使用了不合格的函数名称1}}作为标题。因此,使用cstring
或使用string.h
的优势没有明显的优势,我认为如果以适当的方式使用,可以在C ++中使用。
答案 1 :(得分:4)
在C ++中,C语言头在命名空间std下定义。因此,如果您在C ++中使用这些标头,请使用cstring并消除.h。
答案 2 :(得分:4)
你可以使用string.h进行C&amp; C ++。
在C ++ 98规范中,它定义了cstring(在主要规范中)和string.h(在附件D.5中,标准C库头,为了兼容性),它定义了一些与string.h相同的字符串函数。 C.在现实世界中,所有C ++编译器都将提供string.h以与C代码兼容。
所以,在我看来,由于C ++代码可能由C编码器维护,而习惯来自C,我更喜欢string.h。它足够清晰,广为人知,兼容性更强(使用C)。
BTW,我在C ++中列出了所有18个头文件,以便与C语言兼容,在C ++ 98规范中: 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
答案 3 :(得分:4)
string.h 与 cstring
之间存在细微差别Alf P. Steinbach的答案(可以作为对问题的评论):
string.h
将标识符放在全局命名空间中,也可以将它们放在标准命名空间中。虽然cstring
将标识符放在标准名称空间中,但也可以将它们放在全局名称空间中。您绝对不希望cstring
行为,因为代码例如只使用strlen
可以在一个编译器上正常工作,然后无法用另一个编译器编译。这是非常令人不快的惊喜。因此,对于 C和C ++ ,请使用更安全的string.h
。
答案 4 :(得分:2)
标头的C ++版本实际上与C版本有一些差异。在C中,某些类型是作为typedef实现的,但是对于C ++来说,它可以防止模板特化等事情对这些类型*进行处理,因此C ++会将一些C typedef转换为实际类型。这意味着包含这些typedef的C ++的C ++版本必须省略它们。
C ++还允许重载,因此<cstring>
的C ++版本指定C函数的一些重载,以允许函数返回指向非const数据的指针,如果输入参数是指向非const数据的指针,而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特化。
答案 5 :(得分:1)
显然cstring
适用于C ++,string.h
适用于C。
值得一提的是,如果您从string.h
切换到cstring
,请记住在所有字符串函数调用之前添加std::
。
答案 6 :(得分:0)
使用<cstring>
时,一些答案建议使用std::
命名空间。但是,代码仍将在没有std
名称空间的情况下进行编译和运行。这是因为:
<cstring> = "string.h" + <functions defined in the std namespace>
这样做是为了保持与C的兼容性。
自己添加<cstring>
并同时调用memcpy()
和std::memcpy()
进行尝试。