【问题标题】:Question regarding pointer arithmetic and strings关于指针算术和字符串的问题
【发布时间】:2021-06-28 13:17:22
【问题描述】:

考虑以下程序:

#include <iostream>
using namespace std;
int main()
{
    const char* p = "12345";
    const char **q = &p;
    *q = "abcde";
    const char *s = ++p;
    p = "XYZWVU";
    cout << *++s;
    return 0;
}

我已经算出指针算术,并且我已经算出s指向p的第三个字符。但是,在执行该程序时,它会打印“c”(这是 abcde 的第三个字符)而不是“Z”。我在这里的疑问是在这条线上

 p = "XYZWVU";

我们已经让指针p指向字符串的第一个字符(XYZWVU),那么为什么这个程序不打印'Z'呢?

请指导。

【问题讨论】:

  • 更简单的版本:const char* p = "12345"; const char *s = p; p = "XYZWVU"; std::cout &lt;&lt; *s;。更改 p 的值不会更改 s 的值。 s 仍然指向 "12345"
  • 你能解释一下改变 p 的值如何不影响 s 的值吗? @PeteBecker
  • 你的问题和int i = 5; int j = i; i = 6;一脉相承,怎么j还是5?
  • @loveofprogramming -- 更改 p 不会修改 s,因为 C++ 不是电子表格。 const char *s = p; 复制 p 的值到s。它不记得它是从哪里得到这个值的。

标签: c++ pointers declaration string-literals pointer-arithmetic


【解决方案1】:
#include <iostream>
using namespace std;
int main()
{
    const char* p = "12345"; // have p point at "12345"
    const char **q = &p;     // have q point at p
    *q = "abcde";            // change what q points at (p) to "abcde"
    const char *s = ++p;     // increment p and assign its result ("bcde") to s
    p = "XYZWVU";            // have p point at "XYZWVU"
    cout << *++s;            // increment s and dereference the result ("cde")
    return 0;
}

p = "XYZWVU";是在p的值赋值给s之后完成的,所以不会影响s的值。

【讨论】:

  • 但是在p="XYZWU"这一行,当p开始指向XYZWU时,那么s也应该只指向字符串的第三个字符(XYZWU),怎么能说s会指向字符串的第三个字符(abcde)?
【解决方案2】:

考虑一下这段代码sn-p

const char* p = "12345";
const char **q = &p;
*q = "abcde";
const char *s = ++p;

在声明变量s之前,指针p的值被指针q改变了

*q = "abcde";

其实这个语句等价于

p = "abcde";

因为解引用指针 *q 我们得到指针 p。

所以在初始化指针s之后

const char *s = ++p;

它指向字符串文字"abcde"的第二个字符。

此声明

p = "XYZWVU";

不影响变量 s。指针 s 和 p 相互独立。

所以这个说法

cout << *++s;

输出字符串文字“abcde”的第三个字符。

你应该明白指针 p 和 s 占用不同的内存范围。它们是不同的对象。

在此声明中

const char *s = ++p;

表达式++p的值被赋值给指针s。该值是字符串文字“abcde”的第二个字符的地址。因此,您可以重新分配指针 p 但指针 s 仍将指向(将具有相同的分配值)指向该字符串文字的第二个具有静态存储持续时间的字符。重新分配指针 p 后,字符串文字并没有消失。也就是说,字符串文字的存在与您是否更改了指针 p 无关。

【讨论】:

  • 我不同意,指针 p 和 s 是如何相互独立的?因为,我们已经定义了这两个指针之间的关系:const char *s = ++p,怎么能说改变p不会影响s呢?
  • 如果你能用更多的例子或一些相关的理论/参考来举例说明这一点,我们将不胜感激。
  • @loveofprogramming 分配没有定义关系。它执行值复制,除非运算符重载。在 C++ 中,= 是一个赋值,而不是一个等式。
  • @loveofprogramming 查看我的附加帖子。
  • @loveofprogramming 指针没有什么特别之处。如果你有int x = 1; int y = x; x = 2;,你对y的值是1感到惊讶吗?
【解决方案3】:

您的代码涉及两种类型的地址:内存位置的地址和在这些内存位置存储的地址。

例如,指针变量 p 位于内存中的特定地址,例如 0x1234。您的代码将此地址分配给 q。 p 的值(您之前写入 p 的那个),比如说 0xAABB,是地址存储在内存位置 0x1234。假设内存位置 0x1234 的内容发生变化,要么覆盖 p,要么写入 *q。比方说,它变成了 0xAACC。这种变化分别在 *q 和 p 中可见,因为 q 指向 p 所在的地址(q 的值是 0x1234)。变量 p 和 q 相连:*q 是 p 的别名。

指针变量 s 也位于特定地址,比如 0x5678。但是通过将 ++p 分配给 s,您只需将地址 0xAACD 存储到内存位置 0x5678。内存位置 0x5678 连接到内存位置 0xAACD(因为这个分配),但不连接到内存位置 0x1234。对 p 的后续更改(内存位置 0x1234 的内容)不会影响 s(内存位置 0x5678 的内容)。它们没有连接。

p 和 s 是否是指针变量无关紧要。在重新定义变量的上下文中,它们的行为就像标量变量。只是它们包含地址而不是标量值。如果将包含 p 的表达式分配给 s,然后重新定义 p,则更改不可能传播到 s 的值。

【讨论】:

    猜你喜欢
    • 2011-02-03
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 2015-10-19
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多