指针算术?这三个表达式有什么区别?

时间:2011-05-12 23:11:27

标签: c++ pointers pointer-arithmetic

所以我想了解两件事:

  1. 这三个表达有什么区别?
  2. 第一个表达式(A)的等价物是什么?
  3. 以下是代码(已修复):

    #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;
    }
    

5 个答案:

答案 0 :(得分:3)

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

*(ppDoubleArray[i])

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

(*ppDoubleArray)[i]

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

答案 1 :(得分:1)

你有一个指向double的指针。可以把它想象成一个双打数组的指针。无论哪种方式,以下是它们的含义:

  1. double expressionA = *(*ppDoubleArray + 1);与:double expressionA = *((*ppDoubleArray) + 1);
  2. 相同
  3. double expressionB = **(ppDoubleArray + 1);与:double expressionB = *(*(ppDoubleArray + 1));相同,这意味着您要取消引用我猜不存在的ppDoubleArray[1]
  4. double expressionC = *ppDoubleArray[i];与:double expressionC = *(ppDoubleArray[i]);相同 - 再次,您要取消引用不存在的ppDoubleArray[i]
  5. 像其他人一样,你需要注意偏好的顺序。基本上,首先取消引用然后索引你的数组。

答案 2 :(得分:1)

double expressionB = **(ppDoubleArray + 1);

让我们看看这个人的内存,在堆栈上你有一个指向double的指针。因此,如果它是32位处理器的内存地址,那么堆栈可能类似于:

stack:  |ppDoubleArray ptr    |local vars, other args, or garbage |more locals/etc
addr:   |0 bytes from stack   |4 bytes from stack                 |8bytes...

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

  (ppDoubleArray + 1)

这表示“将一个指针移过ppDoubleArray”。转到下一个指针,转到内存中的下一个位置。在ppDoubleArray之后,记忆中的下一个位置是什么?查看上面的堆栈,它可能是一些局部变量或另一个参数。那么现在你有谁知道什么(也许是长度的内容?其中一个双打?垃圾?)你会把它当作某个地方的有效地址来对待它。然后通过解除引用来跟随该假定的指针:

   **(ppDoubleArray + 1)

崩溃!

因此,例如,如果长度为5,则ppDoubleArray + 1可能会获取5并取消引用“5”以寻找该地址的内容。

此代码:

   double expressionC = *ppDoubleArray[i];

以相同的方式工作,[] take precedence取代引用。所以你去了ppDoubleArray以后的第i个内存位置并假设它指向你的数组。

重新安排父母的操作顺序,但是有效:

   (*ppDoubleArray)[i]

答案 3 :(得分:0)

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

第二个崩溃是因为你在指向数组的指针中添加了一个而没有从中选择正确的索引。

第三个因为运营商的优先权而崩溃。你正在选择不是数组的i元素(除非我是0),然后解除引用它。

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

答案 4 :(得分:0)

aSCII艺术时间:
---> = derefering

double expressionA = *(*ppDoubleArray + 1);

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

double expressionB = **(ppDoubleArray + 1);

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

double expressionC = *ppDoubleArray[i];

ppDoubleArray
     +i
      . ---> . ---> expressionC