基本的c风格字符串内存分配

时间:2011-11-15 20:29:39

标签: c++ memory c-strings

我正在开发一个现有代码的项目,该代码主要使用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 

是指向一个足够大的内存区域的指针,用于保存字符串文字“这是一个测试”。如果是这种情况,那我怎么能在同一个位置存储更长的字符串呢?由于尝试将长字符串塞入为较短的字符串留出的空间,我预计它会在执行此操作时崩溃。

显然对这里发生的事情有一个基本的误解,所以我感谢任何帮助理解这一点。

6 个答案:

答案 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实际上是从第一个字符位置开始循环,直到找到一个空字符。