我正在开发一个现有代码的项目,该代码主要使用C ++但使用c风格的字符串。请采取以下措施:
#include <iostream>
int main(int argc, char *argv[])
{
char* myString = "this is a test";
myString = "this is a very very very very very very very very very very very long string";
cout << myString << endl;
return 0;
}
编译并运行正常,输出为长字符串。
但我不明白为什么它有效。我的理解是
char* myString
是指向一个足够大的内存区域的指针,用于保存字符串文字“这是一个测试”。如果是这种情况,那我怎么能在同一个位置存储更长的字符串呢?由于尝试将长字符串塞入为较短的字符串留出的空间,我预计它会在执行此操作时崩溃。
显然对这里发生的事情有一个基本的误解,所以我感谢任何帮助理解这一点。
答案 0 :(得分:14)
您不会更改内存的内容,而是将指针的值更改为指向包含"this is a very very very very very very very very very very very long string"
的不同内存区域。
请注意,char* myString
仅为指针分配足够的字节(通常为4或8个字节)。执行char* myString = "this is a test";
时,实际发生的事情是程序开始之前的 ,编译器在可执行映像中分配空间 并将"this is a test"
放入记忆。然后,当你执行char* myString = "this is a test";
它实际做的只是为指针分配足够的字节,并使指针指向它在编译时已在可执行文件中分配的内存。
所以如果你喜欢图表:
char* myString = "this is a test";
(allocate memory for myString)
---> "this is a test"
/
myString---
"this is a very very very very very very very very very very very long string"
然后
myString = "this is a very very very very very very very very very very very long string";
"this is a test"
myString---
\
---> "this is a very very very very very very very very very very very long string"
答案 1 :(得分:5)
内存中有两个字符串。首先是"this is a test"
,让我们说它从地址0x1000开始。第二个是"this is a very very ... test"
,它从地址0x1200开始。
通过
char* myString = "this is a test";
你创建一个名为myString
的变量并为其分配地址0x1000。然后,通过
myString = "this is a very very ... test";
你指定0x1200。由
cout << myString << endl;
你只需要打印从0x1200开始的字符串。
答案 2 :(得分:2)
您有两个类型为const char[n]
的字符串文字。这些可以分配给char*
类型的变量,它只不过是指向char
的指针。每当你声明一个指向-T类型的变量时,你只是声明指针,而不是它指向的内存。
编译器为两个文字保留内存,您只需获取指针变量并将其指向一个接一个的文字。字符串文字是只读的,它们的分配由编译器处理。通常,它们存储在受保护的只读存储器中的可执行映像中。字符串文字的生命周期通常等于程序本身的生命周期。
现在,如果您尝试修改文字的内容,那么它将是UB,但您不会。为了防止您自己尝试修改错误,最好将变量声明为const char*
。
答案 3 :(得分:2)
在程序执行期间,分配一个包含“this is a test”的内存块,并将该内存块中第一个字符的地址分配给myString变量。在下一行中,分配了一个单独的内存块,其中包含“this is a very very ...”,并且该内存块中第一个字符的地址现在被分配给myString变量,替换它用于的地址。使用新地址存储到“非常非常长”的字符串。
只是为了说明,假设第一块内存看起来像这样:
[t] [h] [i] [s] [] [i] [s] [] [a] [] [t] [e] [s] [t] 让我们说这个序列/字符数组中第一个't'字符的地址是0x100。 所以在第一次分配myString变量之后,myString变量包含地址0x100,它指向“这是一个测试”的第一个字母。
然后,一个完全不同的内存块包含:
[t] [h] [i] [s] [] [i] [s] [] [a] [] [v] [e] [r] [r] [y] ... 我们只是说第一个't'字符的地址是0x200。 所以在myString变量的第二次赋值之后,myString变量NOW包含地址0x200,它指向“这是非常非常非常......”的第一个字母。
由于myString只是一个指向字符的指针(因此:“char *”是它的类型),它只存储一个字符的地址;它不关心数组应该有多大,它甚至不知道它指向一个“数组”,只是它存储了一个字符的地址......
例如,您可以合法地执行此操作: char myChar = 'C';
/* assign the address of the location in
memory in which 'C' is stored to
the myString variable. */
myString = &myChar;
希望这很清楚。如果是这样,upvote /接受答案。如果没有,请发表评论,以便我澄清。
答案 4 :(得分:1)
字符串文字不需要分配 - 它们按原样存储,可以直接使用。本质上,myString是一个指向一个字符串文字的指针,并被更改为指向另一个字符串文字。
答案 5 :(得分:0)
char*
表示指向包含字符的内存块的指针。
C样式字符串函数获取指向字符串开头的指针。他们假设有一系列以0-null字符结尾的字符(\ n)。
那么什么&lt;&lt; operator实际上是从第一个字符位置开始循环,直到找到一个空字符。