0

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

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

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

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

> *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

4 回答 4

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'的双指针。也许试试他们的地址。其次,您可能希望重新审视如何在函数中使用这些指针进行取消引用,因为这也可能需要工作。

于 2012-09-17T03:20:24.097 回答
2

问题不在于从double**函数内部的 when 检索值,这很简单。问题是您正在创建一个数组而不是一组指针。您的函数不能接受 this 作为参数,并且当您尝试使用(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.
于 2012-09-17T04:08:24.270 回答
1

If the function takes a pointer to pointer to double, and you begin with an actual array, then you'll need to make a copy of the address of the array, and then pass a reference to that:

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);

In the sum function, de-reference to get back to the arrays: *A[0].

于 2012-09-17T02:43:48.667 回答
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);

另一个注意事项:在您发布的代码中,您的函数返回 (double**) 而不是双精度值。我认为这不容易奏效。首先,一个名为 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);

......但是,这又是丑陋的,不安全的,而且实际上做起来也无济于事。为您想做的工作使用正确的类型要好得多。

于 2012-09-17T04:16:02.750 回答