【问题标题】:C , regarding pointers (or pointers to pointers?), **, and mallocC ,关于指针(或指向指针的指针?)、** 和 malloc
【发布时间】:2017-05-13 07:36:31
【问题描述】:

正如标题中所说,我有一个关于使用 * 两次的问题,就像在以下代码的 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);
    }
}

【问题讨论】:

  • SPPoint** parr; 是指向(一个或多个)指针的指针
  • SPPoint* spPointCreate(...) BTW:SPPoint 不是类型化的。您使用的是 C++ 编译器吗?
  • 在头文件中,抱歉没有包含。
  • 它在在哪里并不重要:在C中,结构定义等同于类型化结构。
  • 我明白了,这很有趣,因为我的课程人员给了我们带有以下行的头文件:( typedef struct sp_point_t SPPoint; ),并告诉我们我们需要在C 文件。那么如果它在头文件中typedef,那么它是否也必须像在C文件中那样?

标签: c memory malloc dynamic-memory-allocation


【解决方案1】:

当使用动态分配的数组时,它通常是通过一个指向数组第一个元素的指针来“处理”的,并且还有一些知道长度的方法,例如显式存储长度,或者有一个结束标记.

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

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

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

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

  • nSPPoints分配一块足够大的内存
  • 初始化分配空间内的每个SPPoint

如果您已尝试过此操作但遇到问题,请发布一个新问题,显示您的代码并解释您遇到问题的位置。

【讨论】:

    【解决方案2】:

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

    然而,并不是所有的指针都是数组。 SPPoint** parr 充当数组,保存指向 SPPoint 类型的单个结构的指针。

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

    使用指向 SPPoint 的指针(就像现在一样)是有利的原因是您可以查看或修改单个元素而无需复制整个结构。

    【讨论】:

    • 一个数组不能被认为是一个指针,就像一个int不能被认为是一个double
    • ...确实,将数组与指针混淆会导致各种误解和伴随的错误。
    • @Rusty,你还是没明白。数组和指针是完全不同的东西。 No 指针是一个数组,指针也永远不会充当数组,或者数组的行为类似于指针。实际情况是,当对数组类型的表达式求值时,结果是指向数组第一个元素的指针。当然,这样一个指针的行为就完全像一个指针。事实证明,理解这一点相当重要,因为如果您不理解这一点,关于 C 的许多事情就会显得不一致。
    • @Rusty 一个数组不存储内存地址(除非它是一个指针数组)。一个数组一个地址,但是一个int和任何其他对象也有
    • 作为@M.M.也就是说,数组存储内存地址,除非它们的元素是指针的特殊情况。你提出的反对意见围绕着我之前提到的一些误解。其中: (i) 没有 C 函数接受数组作为参数; (ii) 索引运算符 ([]) 在技术上是 pointer 运算符,而不是数组运算符。您没有提出这个问题,但我们经常在这里看到的另一个问题是二维数组对应于所谓的双指针的错误期望。这也是 C 没有全数组赋值的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 2012-08-17
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    相关资源
    最近更新 更多