2

起初我猜想 k1 的值不会在主空间中。但是后来我意识到一个数组是一个指针,那么有什么区别吗?我认为这是相同的,但也许任何人都可以找到其他一些技术差异。也许更快地传递指针?

#include <iostream>

using namespace std;

void g(double [],int );
void f(double* [],int );

int main()
{

    int n = 10;
    double *k1, *k2;

    k1 = new double[n];
    k2 = new double[n];

    g(k1,n);
    f(&k2,n);

    for(int i = 0;i <n;i++)
    {
        cout << k1[i]<< " ";
        cout << k2[i] << endl;
    }

    delete [] k1;
    delete [] k2;

    return 0;
}


void g(double h[],int n)
{
     for(int i = 0;i <n;i++)
        h[i]=i;
}

void f(double* h[],int n)
{
     for(int i = 0;i <n;i++)
        (*h)[i]=i;
}
4

6 回答 6

11

首先,数组不是指针。这是一个包含 10 个双精度数的数组:

double a[10];

这是一个指向双精度的指针:

double *p;

这是一个指向 10 个双精度数组的指针:

double (*pa)[10];

这是一个指向双精度的指针数组:

double *pa[10];

数组和指针只有在声明为函数参数时才相同。但是数组可以转换(衰减)为指向数组第一个元素的指针:

double a[10];
double *p = a;
double *q = &a[0]; //same as p

在您的示例代码中:

double *x = new double[10];

您正在创建一个包含 10 个双精度的动态数组并获取指向该数组第一个元素的指针。您还可以创建一个新数组并获取一个指向数组的指针:

double (*x)[10] = new double (*)[10];

但是这种奇怪的语法显示很少有用。

关于函数,这是一个采用双精度数组的函数:

void g1(double h[], int n);

这是一个将指针指向 10 个双精度数组的函数:

void g2(double (*h)[10]);

在指向数组的情况下,您需要指定数组的大小,因为您无法创建指向未知大小数组的指针。

这就是为什么数组实际上作为指针传递给函数的原因。但是指向数组第一个成员的指针,而不是指向数组本身的指针。所以第一个功能实际上与这个相同:

void g1(double *h, int n);

由于您只将指针传递给数组的第一个成员(指向双精度的指针),因此您还需要在附加参数中指定数组的大小。优点是您可以传递任意大小的数组。甚至是数组的拼接:

double x[20];
g1(x + 10, 5); //pass x[10..15]

关于哪个更快,它们都是相同的,它们实际上是指向相同内存地址的指针。请注意,数组仅在它们是结构的一部分时才通过副本传递,并且结构是按值传递的。

我的建议是:如果您使用 C 坚持惯用的 C,则在必要时使用指向数组第一个成员的指针,并尽可能避免使用指向数组的语法。如果您使用 C++,请使用容器、迭代器和范围。

于 2013-07-26T20:06:52.800 回答
3
void f(double* h[],int n)

不接受指向数组的指针。你已经声明它接受一个指针数组。

它起作用的唯一原因是声明为数组的函数参数被默默地转换为指针,因此它等效于:

void f(double** h,int n)

毕竟这是你想要的。

此(被 g++ 拒绝)代码将使用指向数组的指针:

void f(double (*h)[],int n)
于 2013-07-26T20:03:19.170 回答
2

有了这个声明:

void f(double* [],int );

您是说,作为第一个参数,您正在获取一个指向double.

当您使用 取消引用该参数(被视为指向指针的指针)时(*h),您实际上获得了数组第一个位置的地址。

于 2013-07-26T20:05:28.560 回答
1
void g(double h[],int n);

在该函数中,您在技术上传递了一个指针。

void f(double* h[],int n);

然而,在这一个中,您传递一个指向数组的指针,该数组解析为指向指针的指针,因为它是一个函数参数*。

*归功于本·沃伊特

于 2013-07-26T19:59:36.970 回答
1

即使您按值传递指针,它指向的内存仍然可以由函数更改。

于 2013-07-26T20:00:14.313 回答
0

许多程序员对编译器如何工作都有一个心理模型,其中包括“数组只是一个指针”。这个模型不正确。

 typedef int[10] Array;
 typedef Array * PointerToArray;
 typedef int * Pointer;

 Array a = {0,1,2,3,4,5,6,7,8,9};
 PointerToArray pa;
 Pointer pint = a;   // the compiler casts this automatically to a different type.

此时 pint 和 pa 具有相同的二进制值,但 pa[1] 和 a[1] 不引用内存中的相同位置。了解原因很重要。

于 2013-07-26T20:08:12.870 回答