【问题标题】:Pointers to pointers in arrays指向数组中指针的指针
【发布时间】:2020-03-01 02:52:09
【问题描述】:

我对 C++ 中的指针和数组有疑问。我不确定这部分代码到底在做什么。正如我看到的那样, iarray 被声明为普通数组。但是 q 像二维数组一样被访问。

    int iarray[10];
    int *p = iarray;
    int **q = &p;
    q[0][2] = 25;

如果我将 iarray 更改为:

    int iarray[10]{3,2};
    int *p = iarray;
    int **q = &p;
    q[0][2] = 25;

    cout << q[0][0] << endl;
    cout << q[1][0] << endl;

第一个将打印 3,正如我在上面声明的那样,我理解它。但是第二个是空白的,我不明白为什么。

【问题讨论】:

  • 2 存储在q[0][1],而不是q[1][0]
  • 请注意,取消引用 q[1] 会导致未定义的行为。
  • 问题是我确实知道它在做什么,但不知道如何以有意义的方式表达它。但基本上,它是在尝试构建一个事实上的二维数组,然后取消引用超出范围的内存。

标签: c++ pointers multidimensional-array


【解决方案1】:

让我们一次看一条指令:

int iarray[10]; 将在内存中保留 10 个 int 大小的字节。如果sizeof(int) == 4它将保留40个字节。假设内存范围设置在 0x10 - 0x37 之间。

int *p = iarray 保留 4 个字节(如果我们假设我们在 32 位处理器上运行)并将起始地址存储到前一条指令中保留的 40 个字节。 p 是我们用来指代这 4 个字节的简写。假设这 4 个字节存储在 0x50 - 0x53。

int **q = &amp;p 多保留 4 个字节来保存 p (0x50) 的起始地址。 q可以存储在0x60-0x63。

c++ 中指针上的数组索引运算符是指针算术的简写。例如,q[N]*(q + N) 相同,因此,在我的示例中,q[0] 将为您提供地址 0x60-0x63 中保存的值,即 0x50。 如果再次使用索引运算符,它将应用于新地址(0x50),因此q[0][2] 等同于p[2],即iarray[2]

q[1] 等价于*(q + 1) = *(0x60 + 0x4) =*(0x64)。如果您看上面,我们从不保留地址 0x64,因此我们正在从我们不拥有的内存中读取 - 未定义的行为。

【讨论】:

  • 好的,我明白了。如果我们有一个从 1 到 9 的数字列表,只是为了确定 iarray 的结构是 {1,2,3,4,5,6,7,8,9}。或者结构是这样的{*p1, *p2, *p3} 其中 *p1 = {1,2,3} , *p2 = {4,5,6}, *p3 = {7,8,9}。
  • 能否请您重新表述您的问题?我不明白。您是指将 iarray 定义为int iarray[10]{3,2} 的情况吗? int iarray[10]{3,2} 保留 10 个连续整数并初始化 iarray[0] = 3 和 iarray[1] = 2。
  • 抱歉,我所说的结构是指数据如何以数组的形式呈现。据我所知,普通的二维数组类似于 {{1,2,3},{4,5,6},{7,8,9}}。如果能给出一个例子,那将是非常感谢。 :)
  • 我不知道答案,但我怀疑你是对的。如果您声明int arr[3][2],编译器将保留 6 个连续整数并将它们存储为 1,2,3,4,5,6...。当您使用索引运算符时,编译器将知道如何计算正确的偏移量:[2][1] 将是 *(arr + 2 * 3 + 1)。由于您是 C++ 新手,我建议您使用 std::vector<:vector>> 来表示矩阵 - 它更容易理解且更难误用。
【解决方案2】:

让我们看看这个:

int iarray[10]; // declare a array of 10 ints
int *p = iarray; // p is used like an alias for iarray, an int[] is also an int*
int **q = &p; //q is a pointer to pointer p

q 仅指向单个值。您可以将q 视为只有一个条目的数组。你也可以写成int *q[] = { &amp;p };

所以q[1][0] 是未定义的行为,因为q[1] 已经超出范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    相关资源
    最近更新 更多