[英]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);
它们都以双指针传递(不要问为什么),并且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);
所以问题是,当指针/双指针传递时,我应该如何准确地获取数组中的元素?
您对函数的数组传递完全不正确。 最好将双指针视为指针到指针。 以同样的方式,指针是一个将地址保存到某个地方的变量,指针到指针保存一个类似的地址,恰好碰巧它引用的内存是另一个指针占用的内存。 最好用示例来描述:
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.