如何访问作为双指针传递的数组元素?

时间:2012-09-17 02:39:50

标签: c++

这是函数的原型,sum,我用来汇总两个任意数组的元素。

double **sum(double **A, double **B, int M, int N);

它们都作为双指针传递(不要问为什么),MN应该分别是数组的维度。

我遇到的麻烦是,在函数的实现中,访问数组的元素。我试过“引用”数组(或者我认为),但无济于事。以下是我尝试过的事情:

> *A;  // Gives me an address, 0xf5c28f5c, not a number
> **A; // Error
> &A;  // Gives me the address of A

这就是我将数组传递给sum的方法,如果它有用的话:

double a[] = {5.34, 5.23, 6.5, 3.51};
double b[] = {74.3, 42.1, 642.2, 54.2};

sum( (double **) a, (double **) b, 4, 4);

所以问题是,当我通过指针/双指针传递时,我应该如何获取数组中的元素?

4 个答案:

答案 0 :(得分:3)

您的数组通道功能完全不正确。双指针最好被认为是指向指针的指针。以同样的方式,指针是一个变量,它将地址保存到某个地方的内存中,指向指针的指针保存一个类似的地址,它所引用的内存恰好是另一个指针占用的内存。最好通过示例来描述:

include <stdio.h>

int main(int argc, char* argv[])
{
    int a = 5;
    int *p = &a;
    int **pp = &p;
    printf("pp=%p, &p=%p, p=%p, &a=%p *p=%d\n", pp, &p, p, &a, *p);
    return 0;
}

在我的MBA 64位上,这给了我们:

pp=0x7fff50828bc8, &p=0x7fff50828bc8, p=0x7fff50828bd4, &a=0x7fff50828bd4 *p=5

掌握这一点,我认为你会在你的代码中发现你的问题,其中第一个问题就是强调“a”和“b”的双重指针。也许试试他们的地址。其次,你可能想要重新审视你如何使用这些指针来解释你的函数,因为很可能需要工作。

答案 1 :(得分:2)

问题不在于在函数内部从double**检索值时,这是微不足道的。问题是你正在创建一个数组而不是一组指针。您的函数不能接受此参数作为参数,当您尝试使用(double**)进行投射时,A参数会在**进行访问时导致访问冲突。

double** sum(double** A, int size)
{
  printf("First element: %f", A[0][0]); // Print the first element      
  printf("Last element: %f", A[size-1][size-1]); // Print the last element.
  return A;
}


const unsigned int SIZE = 4;
double** a = new double*[SIZE];
for(int i=0; i<SIZE; i++)
{
  a[i] = new double[SIZE];
}

a = sum(a, SIZE);

使用像这样的指针(而不是专门用于处理这些情况的容器)的最大痛苦是你的记忆管理可能会失控。

for(int i=0; i<SIZE; i++)
{
  delete [] a[i]; // Free the inner array
}
delete [] a; // Free the outer array.

答案 2 :(得分:1)

如果函数获取指向double的指针,并且您从实际数组开始,那么您需要复制数组的地址,然后传递对该数据的引用:

double a[] = {5.34, 5.23, 6.5, 3.51};
double b[] = {74.3, 42.1, 642.2, 54.2};

double *aPtr = a;
double *bPtr = b;
sum(&aPtr, &bbtr, 4, 4);

sum函数中,取消引用以返回数组:*A[0]

答案 3 :(得分:1)

显而易见的解决方案是将数组作为指针传递,而不是作为双指针传递:

double sum(double *A, double *B, int M, int N)
{
   double ret = 0.0;
   for (int i=0; i<M; i++) ret += A[i];
   for (int j=0; j<N; j++) ret += B[j];
   return ret;
}

double a[] = {5.34, 5.23, 6.5, 3.51};
double b[] = {74.3, 42.1, 642.2, 54.2};
double s = sum( a, b, 4, 4);
printf("The sum is %f\n", s);

......这样做是最简单的事情。但是,如果您受到使用双指针的函数签名的现有API的限制,那可能是因为API希望允许被调用函数能够修改传递给它的指针。传递指向指针的指针允许被调用的函数在需要时写入指向指针,例如:

double sum_and_change_pointers(double ** A, double ** B, int M, int N)
{
   // Compute sum
   double ret = 0.0;
   for (int i=0; i<M; i++) ret += (*A)[i];
   for (int j=0; j<N; j++) ret += (*B)[j];

   // And just for fun, modify the caller's pointer-values too
   static double some_other_array[5] = {0,0,0,0,0};
   *A = some_other_array;
   *B = some_other_array;

   return ret;
}

在这种情况下,函数将被调用如下:

double a[] = {5.34, 5.23, 6.5, 3.51};
double b[] = {74.3, 42.1, 642.2, 54.2};
double * pa = a;  // copy address of arrays into pointers
double * pb = b;  // because changing the address of an array itself wouldn't work
printf("Before calling sum_and_change_pointers, pa=%p and pb=%p\n", pa, pb);
double s = sum_and_change_pointers( &pa, &pb, 4, 4);
printf("After calling sum_and_change_pointers, s=%f, pa=%p and pb=%p\n", s, pa, pb);

另一个注意事项:在您发布的代码中,您的函数返回(双**)而不是双精度。我不认为这可以轻松工作;首先,一个名为sum的函数可能会返回一个双精度浮点值,而不是一个指向指针的指针,因此让它返回一个(double **)是没有意义的......但是即使你(由于某种原因)想要这样做,你需要确保你返回的指针指针指向内存中的有效位置(并且该位置指向一个位置)在内存中的有效位置),这在函数内部很难处理,因为函数返回时所有函数的局部变量都会消失。如果您不介意丢失线程安全性,我想您可以使用静态或全局变量来执行此操作:

double ** sub (double ** A, double ** B, int M, int N)
{
   // Compute sum
   double ret = 0.0;
   for (int i=0; i<M; i++) ret += (*A)[i];
   for (int j=0; j<N; j++) ret += (*B)[j];

   static double result;
   result = ret;

   static double * pointerToResult;
   pointerToResult = &ret;
   return &pointerToResult;
}

[...]
double ** s = sum( a, b, 4, 4);
printf("Sum's result was %f\n", **s);

......但同样,这实际上是丑陋,不安全,无益的。为你想做的工作使用正确的类型要好得多。