C ,关于指针(或指向指针的指针?)、**和 malloc

C , regarding pointers (or pointers to pointers?), **, and malloc

如标题所述,我有一个关于使用 * 两次的问题,例如在以下代码的 main 函数中。它 运行,但我不明白为什么在这里使用 **。我想要的是一个 SPPoints 数组,大小为 n,其中 parr 是基地址。为什么在这种情况下**对和*错?谢谢。

SPPoint代码:

struct sp_point_t
{
    double* data;
    int dim;
    int index;
};

SPPoint* spPointCreate(double* data, int dim, int index)
{
    if (data == NULL || dim <= 0 || index < 0)
    {
        return NULL;
    }
    SPPoint* point = malloc(sizeof(*point));
    if (point == NULL)
    {
        return NULL;
    }
    point->data = (double*)malloc(dim * sizeof(*data));
    for (int i = 0; i < dim; i++)
    {
        point->data[i] = data[i];
    }
    point->dim = dim;
    point->index = index;
    return point;
}

这是主要功能:

int main()
{
    int n, d, k;
    scanf("%d %d %d", &n, &d, &k);
    double* darr = malloc(d * sizeof(double));
    if (darr == NULL)
    {
        return 0;
    }
    SPPoint** parr = malloc(n * sizeof(SPPoint*));
    if (parr == NULL)
    {
        return 0;
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < d; j++)
        {
            scanf(" %lf", &darr[j]);
        }
        parr[i] = spPointCreate(darr, d, i);
    }
}

数组的行为类似于指针。例如,int a [] 与 int* a 非常相似。 SPPoint returns 中的每个函数都是一个指向 SPPoint 结构的指针。指向 SPPoint 的指针数组可以写成指向指向 SPPoint 的指针的指针。使用 malloc 命令,您指定一定数量的内存(足以容纳 n 个指向 SPPoint 的指针)用于存储指向 SPPoint 结构的指针。

然而,并不是所有的指针都是数组。 SPPoint** parr 充当一个数组,其中包含指向 SPPoint 类型的单个结构的指针。

数组的行为可能与指针不同,尤其是用于字符串时。

使用指向 SPPoint 的指针(就像您现在这样)的好处在于您可以查看或修改单个元素而无需复制整个结构。

当使用动态分配的数组时,通常 "handled" 有一个指向数组第一个元素的指针,并且还有一些知道长度的方法,例如显式存储长度,或者有一个终结哨兵。

因此,对于代码中动态分配的 SPPoint * 数组,指向其中第一个数组的指针的类型为 SPPoint * *

您现有的代码创建了一个 SPPoint * 数组,即指针数组。这些指针中的每一个都指向 SPPoint 的一个动态分配实例,即您为每个条目单独分配。

这是可行的,但您指出您想要一个 SPPoint 的数组,在这种情况下,指向第一个元素的指针的类型为 SPPoint *.

为了有这样一个数组,是单内存分配。因此,您需要重新设计 spPointCreate 函数。目前,它仅为单个 SPPoint 分配内存并进行初始化。相反,您希望将分配与初始化分开,因为您只需要一次分配但需要多次初始化。您的程序逻辑将如下所示:

  • n SPPoints
  • 分配足够大的内存块
  • 在分配的space
  • 中初始化每个SPPoint

如果您已经尝试过但卡住了,那么 post 一个显示您的代码并解释您卡住的地方的新问题。