关于std :: string与unsigned char []和unsigned char *的不同之处是什么?

时间:2015-09-23 08:42:19

标签: c++ string unsigned-char

我从文件中获取一个字符串,然后将字符串转换为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();

我无法理解他们的不同之处。它们是一样的吗?

3 个答案:

答案 0 :(得分:4)

基础知识

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

unsigned char* cc是指向unsigned char的指针(可能是unsigned char的连续序列(未知长度)的开头)

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

第一个代码示例

在这里,您创建一个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_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".
    

答案 1 :(得分:1)

不,他们不一样。首先:您将message的内容复制到c。在第二个 - 你只需指定指针,将c_str返回c。因此,当消息被更改或销毁时,您将在c中出现垃圾。

答案 2 :(得分:0)

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

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

首先你有什么理由转换成c风格的数组吗?