我从文件中获取一个字符串,然后将字符串转换为unsinged char []。 这是我的代码:
unsigned char c[16];
std::string message = ReadFile(); // get string from file
strcpy((char*)c,message.c_str());
将字符串转换为unsigned char *
unsigned char* c;
std::string message = ReadFile(); // get string from file
c = (unsigned char*)message.c_str();
我无法理解他们的不同之处。它们是一样的吗?
答案 0 :(得分:4)
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字符串(以null结尾)表示,并使用strcpy
将其复制到16-char缓冲区中。不幸的是,你没有检查大小,因此可能会超出缓冲区的末尾并且会导致未定义的行为。 不要这样做。您现在有两份数据副本; 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".
答案 1 :(得分:1)
message
的内容复制到c
。在第二个 - 你只需指定指针,将c_str
返回c
。因此,当消息被更改或销毁时,您将在c
中出现垃圾。
答案 2 :(得分:0)
在第一个示例中,字符串的内容被复制到数组中(尽管16是文件缓冲区的相当短的长度)。现在你有两个不同的容器来保存相同的数据。
在第二个示例中,您读入字符串,然后将其容器的地址传递给指针。因此指针将指向与字符串相同的数据。但是,您无法将const char *转换为非const类型,因此您的示例可能无法编译。
首先你有什么理由转换成c风格的数组吗?