1

所以我试图理解两件事:

  1. 这三种表达方式有什么区别?
  2. 第一个表达式(A)的等价物是什么?

这是代码(固定):

#include "stdafx.h"

void someFunc(double** pArray, int length)
{
    for(int i = 0; i < length; i++)
    {
        //this works perfectly
        double expressionA = *(*pArray + i);
        //this crashes : Unhandled exception at 0x00da13ff in pptrtest.exe: 0xC0000005: Access violation reading location 0xcccccccc.
        double expressionB = **(pArray + i);
        //this crashes : Unhandled exception at 0x00da13ff in pptrtest.exe: 0xC0000005: Access violation reading location 0xcccccccc.
        double expressionC = *pArray[i];
    }
}
int main()
{
    double arr[] = { 1, 2, 3, 4, 5 };

    double* pArr = arr;

    someFunc(&pArr, sizeof arr / sizeof arr[0]);

    return 0;
}
4

5 回答 5

3

我认为问题是,[] 在 * 之前应用,所以在 expr C 中你正在做

*(ppDoubleArray[i])

实际上相当于 expr B,但 expr A 确实

(*ppDoubleArray)[i]

(假设表达式中的 1 应该是 i,否则无论如何都不同)。

于 2011-05-12T23:16:50.043 回答
1

您有一个指向双精度指针的指针。将其视为指向双精度数组的指针。无论哪种方式,以下是它们的含义:

  1. double expressionA = *(*ppDoubleArray + 1);是相同的:double expressionA = *((*ppDoubleArray) + 1);
  2. double expressionB = **(ppDoubleArray + 1);等同于:double expressionB = *(*(ppDoubleArray + 1));这意味着您要取消引用ppDoubleArray[1]我猜测的不存在。
  3. double expressionC = *ppDoubleArray[i];与以下内容相同:double expressionC = *(ppDoubleArray[i]);- 再次,您正在取消引用ppDoubleArray[i]不存在的内容。

就像其他人所说的那样,您需要注意优先顺序。基本上,首先取消引用然后索引您的数组。

于 2011-05-12T23:23:20.290 回答
1
double expressionB = **(ppDoubleArray + 1);

让我们看看这个人的内存,在堆栈上你有一个指向双精度指针的指针。因此,如果它是 32 位处理器的内存地址,堆栈可能看起来像:

堆栈:|ppDoubleArray ptr |local vars、其他 args 或垃圾 |more locals/etc
addr: |0 个来自堆栈的字节 |4 个来自堆栈的字节 |8bytes...

所以当我们看表达式的第一部分

  (ppDoubleArray + 1)

这说“过去一个指针ppDoubleArray”。通过转到内存中的下一个位置来转到下一个指针。记忆中的下一个点是什么ppDoubleArray?查看上面的堆栈,它可能是一些局部变量或其他参数。所以现在你有谁知道什么(可能是长度的内容?其中一个双打?垃圾?)你将把它当作某个地方的有效地址。然后,您可以通过取消引用来遵循那个假定的指针:

   **(ppDoubleArray + 1)

和崩溃!

因此,例如,如果长度为 5,则 ppDoubleArray+1 可能会抓取 5 并取消引用“5”以在该地址寻找某些东西。

这段代码:

   double expressionC = *ppDoubleArray[i];

以同样的方式工作,[] 优先于取消引用。因此,您转到过去的第 i 个内存位置ppDoubleArray并假设它指向您的数组。

但是,重新排列与父级的操作顺序会起作用:

   (*ppDoubleArray)[i]
于 2011-05-12T23:24:57.980 回答
0

假设 ppDoubleArray 是一个指向双精度数组的指针:

第二个崩溃是因为您将一个添加到指向数组的指针而不是从中选择正确的索引。

第三个崩溃是因为运算符的优先级。您正在选择i不是数组的第 th 个元素(除非 i 为 0),然后取消引用它。

这里要记住的重要一点是如何处理指向数组的指针(或指向指针的指针)您取消引用一次以获取数组,此时您可以进行算术然后再次取消引用以获取元素。

于 2011-05-12T23:17:27.540 回答
0

aSCII 艺术时间:
--->= 取消引用

double expressionA = *(*ppDoubleArray + 1);

ppDoubleArray  ---> .  
                    +1  
                    . ---> expressionA

double expressionB = **(ppDoubleArray + 1);

ppDoubleArray
     +1
      . ---> . ---> expressionB

double expressionC = *ppDoubleArray[i];

ppDoubleArray
     +i
      . ---> . ---> expressionC
于 2011-05-12T23:30:50.207 回答