[英]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* c
: c
是指向一个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_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".
不,它们不一样。 首先:您将message
内容复制到c
。 其次 - 您只需分配指针,将c_str
返回到c
。 因此,当消息被更改或销毁时,您将在c
产生垃圾。
在第一个示例中,字符串的内容被复制到数组中(尽管 16 是文件缓冲区的相当短的长度)。 现在你有两个不同的容器来保存相同的数据。
在第二个示例中,您读入字符串,然后将其容器的地址传递给指针。 所以指针将指向与字符串相同的数据。 但是,您不能从 const char * 转换为非常量类型,因此您的示例可能无法编译。
有什么理由让您首先转换为 c 风格的数组吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.