繁体   English   中英

std::string 到 unsigned char[] 和 unsigned char* 有什么不同?

[英]What's the different about std::string to unsigned char[] and unsigned char*?

我从文件中获取一个字符串,并将该字符串转换为未编码的 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();

我不明白他们有什么不同。 他们是一样的吗?

基础知识

unsigned char c[16]c是一个由 16 个unsigned char的数组。

unsigned char* cc是指向一个unsigned char (的也许到连续序列的开始(未知长度的) unsigned char

std::string s : s是一个字符串对象,它在内部保存了一个连续的字符序列,其长度可能会动态变化。 字符串对象还保存字符串的当前长度。


第一个代码示例

在这里,您创建一个 16 个字符的缓冲区,然后创建一个std::string对象,您用ReadFile调用的结果填充该对象。

然后请求std::string对象的 C 字符串(以空字符结尾)表示,并使用strcpy将其复制到 16 字符缓冲区中。 不幸的是,您没有检查大小,因此您很可能会超出缓冲区的末尾并陷入未定义的行为。 不要这样做 您现在有两个数据副本; 一个在std::string ,一个(部分)副本在 16-char 数组中。


第二个代码示例

在第二个示例中,您再次将ReadFile调用的结果分配给std::string ,并再次调用c_str()成员函数以请求以空字符结尾的 C 字符串表示。 这一次,您只需结果指针强制转换为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_funcmy_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".

不,它们不一样。 首先:您将message内容复制到c 其次 - 您只需分配指针,将c_str返回到c 因此,当消息被更改或销毁时,您将在c产生垃圾。

在第一个示例中,字符串的内容被复制到数组中(尽管 16 是文件缓冲区的相当短的长度)。 现在你有两个不同的容器来保存相同的数据。

在第二个示例中,您读入字符串,然后将其容器的地址传递给指针。 所以指针将指向与字符串相同的数据。 但是,您不能从 const char * 转换为非常量类型,因此您的示例可能无法编译。

有什么理由让您首先转换为 c 风格的数组吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM