std::string 与 unsigned char[] 和 unsigned char* 有啥不同?
Posted
技术标签:
【中文标题】std::string 与 unsigned char[] 和 unsigned char* 有啥不同?【英文标题】:What's the different about std::string to unsigned char[] and unsigned char*?std::string 与 unsigned char[] 和 unsigned char* 有什么不同? 【发布时间】:2015-09-23 08:42:18 【问题描述】:我从文件中得到一个字符串,并将该字符串转换为 unsinged char[]。 这是我的代码:
unsigned char c[16];
std::string message = ReadFile(); // get string from file
strcpy((char*)c,message.c_str());
并将字符串转换为无符号字符*
unsigned char* c;
std::string message = ReadFile(); // get string from file
c = (unsigned char*)message.c_str();
我不明白他们有什么不同。他们是一样的吗?
【问题讨论】:
string
是一个 c++ 对象,而 char[]
是一个 c 样式数组。在 C++ 中使用 char[]
是自找麻烦,而实际上有更好的解决方案。
【参考方案1】:
基础知识
unsigned char c[16]
:c
是一个由 16 个 unsigned char
组成的数组。
unsigned char* c
:c
是指向unsigned char
的指针(可能指向unsigned char
的连续序列(长度未知)的开头)
std::string s
:s
是一个字符串对象,它在内部保存一个连续的字符序列,其长度可以动态变化。字符串对象还保存了字符串的当前长度。
第一个代码示例
在这里,您创建了一个 16 字符的缓冲区,然后创建了一个 std::string
对象,并用 ReadFile
调用的结果填充该对象。
然后,您请求 std::string
对象的 C 字符串(以空结尾)表示,并使用 strcpy
将其复制到 16 字符缓冲区中。不幸的是,您没有检查大小,因此您可能会超出缓冲区的末尾并陷入未定义的行为。 不要这样做。您现在有两个数据副本; std::string
中的一个,以及 16 字符数组中的(部分)副本。
第二个代码示例
在第二个示例中,您再次将ReadFile
调用的结果分配给std::string
,并再次调用c_str()
成员函数以请求以空值结尾的C 字符串表示。这一次,您只需cast 结果指针,使其类型为unsigned char*
,并将其分配给您已声明的指针。您只有一份数据副本,并且没有缓冲区溢出。
但是,如果字符串的内容发生变化,指针c
可能会失效。
指南
如果可能,请直接使用std::string
。避免传递char*
或使用char
的数组,因为std::string
会跟踪大小,根据需要调整大小,并为您处理内存分配。
不要做第一个版本。这是不安全的,因为您不检查边界。
避免使用第二个版本;如果你有一个接受 C 字符串的函数,只需将s.c_str()
的结果直接作为参数给它:
void my_func(const char * str);
// ...
std::string s = "Hello";
my_func(s.c_str()); // This is fine!
[注意:这假定您的程序是单线程的,并且字符串s
具有本地范围,即对于my_func
或my_func
可以调用的任何内容的直接操作是不可见的。对s
的任何修改都可能使s.c_str()
返回的指针无效。]
如果您确实需要一个字符串内容的副本,只需在进行任何更改之前将其分配给另一个字符串:
std::string s1 = "Hello";
std::string s2 = s1; // copy the string
s1 = "Goodbye";
my_func(s2.c_str()); // still "Hello".
【讨论】:
你的回答很有用。非常感谢。【参考方案2】:不,它们不一样。首先:将message
的内容复制到c
。在第二个 - 您只需分配指针,将 c_str
返回到 c
。因此,当消息被更改或销毁时,c
中将有垃圾。
【讨论】:
【参考方案3】:在第一个示例中,字符串的内容被复制到数组中(尽管对于文件缓冲区而言,16 是一个相当短的长度)。现在您有两个不同的容器来保存相同的数据。
在第二个示例中,您读入字符串,然后将其容器的地址传递给指针。所以指针将指向与字符串相同的数据。但是,您无法将 const char * 转换为非 const 类型,因此您的示例可能无法编译。
您有什么理由首先转换为 c 样式的数组吗?
【讨论】:
以上是关于std::string 与 unsigned char[] 和 unsigned char* 有啥不同?的主要内容,如果未能解决你的问题,请参考以下文章
将非null终止的unsigned char数组复制到std :: string
复制 std::string::insert(int pos, char ch)
Swig:将 std::vector<unsigned char> 传递给从 c++ 生成的 c# 函数
为 ISO 8859-1 实现 basic_string<unsigned char>