对于长度超过10个字母的字符串,char*的更改没有任何明显的原因.为什么?

With a string longer than 10 letters, char* changes without any apparent reason. Why?

本文关键字:任何明 为什么 char 10个 于长度 字符串      更新时间:2023-10-16

在步骤2中,我只更改name_C的值。为什么name_B也会改变?

这是代码:

#include <cstdlib>
#include <dirent.h> 
#include <iostream>
#include <fstream>
#include <direct.h>
using namespace std;
int main(int argc, char *argv[])
    {
// step 1
        char *name_A;
        char *name_B;
        char *name_C;
        string str_L = "hello";
        string str_M = "stringVar_A";  ;
        name_A = (char *) str_M.c_str();  
        name_B = (char *) (str_L + "-car-" + str_M).c_str();
        name_C = (char *) str_L.c_str();
        cout << " name_A= " << name_A  << endl;
        cout << " name_B= " << name_B  << endl;
        cout << " name_C= " << name_C  << endl << endl << endl;
// step 2
        string str_N = "myStringMyString"; // (in my real code, i can't put this line in step 1)
        string str_R = "ABCDEFGHI" + str_N;   // (in my real code, i can't put this line in step 1)
        name_C = (char *)str_R.c_str();   // change only name_C
        cout << " name_A= " << name_A  << endl;
        cout << " name_B= " << name_B  << endl; // changed, why?
        cout << " name_C= " << name_C  << endl; // changed, ok.
        system("PAUSE");
        return EXIT_SUCCESS;
    };

这里的输出:

    (step 1:)
name_A= stringVar_A
name_B= hello-car-stringVar_A
name_C= hello
    (step 2:)
name_A= stringVar_A
name_B= ABCDEFGHImyStringMyString
name_C= ABCDEFGHImyStringMyString

带有:

string str_N = "myString"; // in step 2...  

name_B不变
如果str_N超过10个字母,为什么name_B会发生变化
有人能帮我理解这种行为吗?

调用c_str返回的指针只有在相应的std::string保持在作用域内且未修改时才有效。

在此之外访问它的行为是不明确的。

例如,(str_L + "-car-" + str_M).c_str();将返回匿名临时c_str。分配后,它将立即无效。在您的情况下,name_B无效。

另外,不要丢弃c_str()const char*返回。它是const,原因很充分:您不应该试图通过该指针修改字符串内容。

您正在导致未定义的行为。

   name_B = (char *) (str_L + "-car-" + str_M).c_str();

根据std::string::operator+的结果创建一个temoprary字符串,从中提取C字符数组,但没有人真正对临时字符串进行Cathed。

当const引用没有捕获临时对象时,它会立即被销毁。字符串析构函数取消分配内部字符数组并使name_B无效。

因此,这是未定义的行为,因为您试图使用不再有效的内存地址。

std::string::c_str()返回指向std::string内部缓冲区的指针,并保证:

  • 它指向一个以NUL结尾的字符串
  • 范围[c_str()c_str() + size()]是有效的

在您的情况下,name_B指向临时对象name_B = (str_L + "-car-" + str_M).c_str();的内部缓冲区,当您尝试使用它时,该缓冲区将导致"未定义的行为"。
当您对堆栈进行一些修改时(您定义了两个新的std::string),您可能会更改name_B所指向的堆栈位置(因为临时内存保留的内存已经释放)。

如果你真的必须从std::string中获得老式的C字符串,请确保:

  • 当CCD_ 24被修改或破坏时,从CCD_
  • 因此您不会从临时调用std::string::c_str()
相关文章: