5

我正在使用主要使用 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 

是一个指向足够大的内存区域的指针,以容纳字符串文字“这是一个测试”。如果是这种情况,那么我如何能够在同一位置存储更长的字符串?我预计它会在这样做时崩溃,因为试图将一根长字符串塞进一个留给较短字符串的空间中。

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

4

6 回答 6

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"
于 2011-11-15T20:31:23.040 回答
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 开始的字符串。

于 2011-11-15T20:37:34.160 回答
2

您有两个类型为 的字符串文字const char[n]。这些可以分配给一个类型的变量char*,它只不过是一个指向 a 的指针char。每当您声明一个指向 T 类型的变量时,您只是在声明指针,而不是它指向的内存。

编译器为这两种文字保留内存,您只需将指针变量一个接一个地指向这些文字。字符串文字是只读的,它们的分配由编译器负责。通常,它们存储在受保护的只读存储器中的可执行映像中。字符串文字的生命周期通常与程序本身的生命周期相同。

现在,如果您尝试修改文字的内容,它将是 UB,但您没有。为了帮助防止自己尝试错误修改,明智的做法是将变量声明为const char*.

于 2011-11-15T20:32:50.003 回答
2

在程序执行期间,会分配一个包含“这是一个测试”的内存块,并将该内存块中第一个字符的地址分配给 myString 变量。在下一行中,分配了一个单独的内存块,其中包含“这是一个非常非常...”,并且该内存块中第一个字符的地址现在分配给 myString 变量,替换了它以前的地址将新地址存储到“非常非常长”的字符串中。

只是为了说明,假设第一个内存块如下所示:

[t][h][i][s][ ][i][s][ ][a][ ][t][e][s][t] 我们只说第一个 't 的地址' 此序列/字符数组中的字符为 0x100。所以在myString变量第一次赋值后,myString变量包含地址0x100,它指向“this is a test”的第一个字母。

然后,一个完全不同的内存块包含:

[t][h][i][s][ ][i][s][ ][a][ ][v][e][r][r][y]...第一个“t”字符的地址是 0x200。所以在 myString 变量第二次赋值后,myString 变量 NOW 包含地址 0x200,它指向“this is a very very very...”的第一个字母。

由于 myString 只是一个指向字符的指针(因此:“char *”是它的类型),它只存储一个字符的地址;它不关心数组应该有多大,它甚至不知道它指向一个“数组”,只知道它正在存储一个字符的地址......

例如,您可以合法地这样做:

    char myChar = 'C';
/* assign the address of the location in 
   memory in which 'C' is stored to 
   the myString variable. */
    myString = &myChar; 

希望这已经足够清楚了。如果是这样,请投票/接受答案。如果没有,请发表评论,以便我澄清。

于 2011-11-15T20:51:02.773 回答
1

字符串文字不需要分配 - 它们按原样存储并且可以直接使用。本质上 myString 是一个指向一个字符串文字的指针,并被更改为指向另一个字符串文字。

于 2011-11-15T20:32:52.047 回答
0

char*表示指向包含字符的内存块的指针。

C 风格的字符串函数获取指向字符串开头的指针。他们假设有一个以 0-null 字符 (\n) 结尾的字符序列。

所以 << 操作符实际上做的是从第一个字符位置循环,直到找到一个空字符。

于 2011-11-15T20:34:27.763 回答