繁体   English   中英

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

[英]How do I access the elements of an array passed as a double-pointer?

这是函数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);

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

您对函数的数组传递完全不正确。 最好将双指针视为指针到指针。 以同样的方式,指针是一个将地址保存到某个地方的变量,指针到指针保存一个类似的地址,恰好碰巧它引用的内存是另一个指针占用的内存。 最好用示例来描述:

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

问题不在于在函数内部从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.

如果函数使用指向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]

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

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 **)而不是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);

...但是,这实际上很难做到,不安全且无济于事。 为您要完成的工作使用正确的类型更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM