c - 指向数组的指针和指向指针的指针的内存分配

标签 c arrays pointers

我对在堆中为二维数组分配内存的不同方法很感兴趣。

访问指向指针的指针和指向一维或多维数组的指针时,似乎使用了相同的表示法。我希望有人澄清每一个的区别和用处。他们都对吗?

第一种方法是将数组存储为指向指针的指针:

char **createTable(int r, int c) {
    char **table;
    int i;
    char *offset;
    table = malloc(r * sizeof (char *) + r * c * sizeof (char));
    if (!table) return NULL;
    offset = (char *) table + sizeof (char *) * r;
    for (i = 0; i < r; i++) {
        table[i] = offset + c * i;
    }
    return table;
}

这种其他方式似乎更快。我想不出像另一个函数一样将它包装在函数中的好方法。

char (*table)[c];
table = (char (*)[c]) calloc(r * c, sizeof (char));

我的理解是否正确,即使数组类似于静态指针,数组本身也可以具有多个维度?

难道我描述的第一种方式是正统方式吗?

最佳答案

不幸的是,似乎没有办法让函数返回指向正确类型化的可变长度数组的指针。你可以尝试这样的技巧:

#include <stddef.h>
#include <stdlib.h>

void* createTable_(size_t r, size_t c) {
  char (*table)[c] = malloc(sizeof(char[r][c]));
  /* do the intialization that you need */
  return table;
}

#define createTable(R, C) ((char(*)[C])createTable_((R), (C)))

int main(int argc, char*argv[]) {
  char (*table)[argc] = createTable(argc, argc);
}

该函数仅返回一个 void* 指针,宏确保正确键入。不幸的是,这样的宏必须对第二个参数求值两次,所以要小心副作用。

编辑,对于您提出的其他子问题:

我不会将指针指向模拟多维矩阵的指针方式称为“正统”,只是过时了。至少对于我所见过的大多数用法而言都是如此。

  • 它很容易出错。你真的必须得到所有的索引计算 正确的。顺便说一句,您还可以通过使用获得更具可读性的内容 sizeof 在数组上,类似于

    malloc(sizeof (char*[r]) + sizeof (char[r][c]))

  • 浪费空间,sizeof(char*[c])部分

  • 它的效率较低,它必须进行额外的间接计算而不是简单的索引计算。

  • 它与其他使用大量矩阵的语言不兼容,例如 Fortran。

关于c - 指向数组的指针和指向指针的指针的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20131721/

相关文章:

c++ - Cuda矩阵复制程序很慢

c++ - 在基类数组中使用子类方法的默认值

java - 在文件数组中查找特定数据?

javascript - 你能帮我理解 sort() 在 Javascript 中是如何工作的吗?

C - 移动链表中的节点

c - 在同一台机器上运行的 C 应用程序之间的套接字通信

c - 如何组织头文件

c - 如何将 (long *) 转换为二维 long 数组

c - C中弹出中间元素

C time.h环绕