2

有件事困扰了我一段时间,我需要一个答案,

char *p = "hello world";
p="wazzup";
p="Hey";

在这里,我声明了一个指向字符串的指针(或者换句话说,我使用指针创建了一个字符串)

我有一些奇怪的结果,如果我使用 char 数组字符串,我通常不会得到

cout <<p<< endl; //"Hey" Gets printer
cout <<p+8<< endl; // I kept adding numbers till "wazzup" got printed
cout <<p+29<< endl; // No matter how much I increment, I cant print "Hello World"

所以我的问题是:

当我更改 char 指针指向的值时。可以

  • 像使用 char 数组一样覆盖原始数据;

  • 或者它在内存中创建一个新字符串并指向它;

  • 还是在旧字符串的开头添加新字符串(包括null);

  • 还是它会在内存中的新位置创建一个新字符串,而我只能偶然打印“wazzup”

4

7 回答 7

4

它不执行上述任何选项。改变指针的值只是改变它指向的内存地址。在分配给 的每种情况下p,它都被设置为指向(不同的)字符串文字的第一个字符 - 它存储在内存中。

使用指向超出字符串文字末尾的指针的行为,例如

cout <<p+8<< endl

未定义。这就是使用指针充满危险的原因。

您看到的行为取决于实现:编译器将字符串文字相邻存储在内存中,因此从一个结尾运行到另一个。当使用不同的编译器编译时,您的程序可能同样崩溃。

于 2012-08-11T14:09:20.993 回答
2

通过添加到指针,您正在增加地址值......所以在打印时它将打印存储在该内存位置的值,而不是其他......

如果你能打印

"hello world"
"wazzup"

那将是侥幸:)

于 2012-08-11T14:10:54.947 回答
1

所有这三个都是字符串文字常量。它们直接出现在可执行文件的二进制文件中,每次分配p时,您都指向内存中的这些位置。它们是完全独立的内存;重新分配p给另一个不会修改任何字符串数据。

于 2012-08-11T14:09:40.163 回答
1

每次分配给它时,您只是使指针指向其他东西。因此,任何地方都没有数据被覆盖的余地。幕后发生的事情取决于实现,因此您所看到的纯属偶然。当你这样做时:

cout <<p+8<< endl;

您正在超出字符串文字的范围,调用未定义的行为。

于 2012-08-11T14:09:43.753 回答
1

当我更改 char 指针指向的值时。可以

- 像使用 char 数组一样覆盖原始数据。不,地址空间的数据部分包含所有三个字符串“Hello World”、“wazzup”和“Hey”。当您更改指针时,您只是将 p 中的值更改为上述任一字符串的起始地址。更改指针指向的地址和更改指针指向的值是两件不同的事情。

- 或者它在内存中创建一个新字符串并指向它。编译器在编译时而不是在运行时创建字符串(字符字节)。

- 或者它是否在内存中的新位置创建了一个新字符串,我只能偶然打印“wazzup”,我认为上面的答案涵盖了这个问题。

- 还是在旧字符串的开头添加新字符串。(包括 null)这取决于编译器规范。

于 2012-08-11T14:11:11.943 回答
1

这三个字符串不在同一个内存位置。这三个内存可能是连续的或不同的位置。如果编译器分配三个内存,那么您会使用 +/- 某个值找到它。这完全取决于编译器。在 c 中,您可以准备好任何内存位置,这样您就不会在 +/- 然后指针 p 时出现任何错误。

于 2012-08-11T14:12:01.420 回答
0

由于它们 3 不是相同的字符串,因此它们位于内存的不同部分。我认为它们可以通过 64 字节对齐来分隔。试试 p+64 :)

只有相同的字符串位于相同的内存位置,并且只有编译器支持它。

在 p+64 有一个概率“wazzup”,在 p+128 有一个概率“嘿”(如果你使用 VC++ 2010 express 并且你有 pentium-m cpu 并且你使用 windows xp sp-3)

cout <<*(p+64)<< endl;
cout <<*(p+128)<< endl;
于 2012-08-11T14:06:54.237 回答