C++ string指针操作输出异常:为何仅显示D而非预期的Dbc?
这问题的核心在于你对std::string指针和C风格字符数组指针的理解有偏差,咱们一步步拆明白:
先看你的C++代码问题出在哪
你写的这段代码里:
string str = "Abc"; string* str_ptr = &str; str_ptr[0] = 'D';
这里的str_ptr是指向std::string对象的指针,根本不是指向字符串内部字符缓冲区的指针!
当你写str_ptr[0]的时候,相当于*(str_ptr + 0)——也就是直接解引用这个指针拿到str对象本身,然后把'D'赋值给它。这操作本质是把一个char类型的值强行赋值给std::string对象,会触发std::string的隐式构造(用单个字符构造一个临时string),然后直接覆盖掉原来str对象的内存结构,把它的内部状态(比如长度、缓冲区指针这些关键数据)全搞乱了。
后面你用sprintf_s(MsgBuff, 300, "%s", str_ptr);的时候,%s期望的是指向C风格字符串的char*指针,但你传的是string*,属于类型不匹配,程序会把std::string对象的内存当成字符数组来解析。因为之前的赋值已经破坏了对象结构,刚好某个位置被改成了'D',后面的内存数据混乱导致字符串提前终止,所以只输出了D。
如果要正确操作std::string的内部字符,应该用str.data()或者str.c_str()(C++11后data()和c_str()基本等价)来获取指向字符缓冲区的指针,比如:
string str = "Abc"; char* str_ptr = const_cast<char*>(str.data()); // 注意:仅当string非const时可修改 str_ptr[0] = 'D'; sprintf_s(MsgBuff, 300, "%s", str.c_str()); OutputDebugStringA(MsgBuff);
这样就能得到预期的Dbc了。
再看C风格char数组为什么正常
而C风格的代码:
char str[] = "Abc"; char* str_ptr = str; str_ptr[0] = 'D';
这里的str本身就是一块连续的字符内存数组,str_ptr = str是让指针直接指向数组的第一个元素。str_ptr[0]就是数组的第一个字符,修改它只是把'A'改成'D',整个数组的结构完全正常,字符串依然是"Dbc",所以输出符合预期。
简单总结:
std::string是一个对象,它的指针指向的是对象本身,不是内部的字符缓冲区- C风格char数组是字符的连续内存块,它的指针直接指向第一个字符
- 别把对象指针当成字符指针来操作,这会直接破坏对象的内存结构!
内容的提问来源于stack exchange,提问作者Derek81

