【问题标题】:**array vs array[][]: are they both 2D arrays?**array vs array[][]:它们都是二维数组吗?
【发布时间】:2022-01-13 04:23:03
【问题描述】:

我的老师告诉我 int **array 不是二维数组,它只是一个指向整数的指针。 现在,在我的一个项目中,我必须动态分配一个二维结构数组,这就是它的完成方式:

struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
    
for (int i = 0; i < columns; i++) {
    array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}

但是这里我们返回一个指向结构体的指针,那么这怎么是一个二维数组呢?

在使用动态分配之前,我有一个静态分配的数组,格式如下: 数组2d[][]

现在我用动态分配代替了它,我也用 **array2d 代替了 array2d[][]。
每个接受 array2d[i][j] als 参数的函数现在都会返回一个错误,指出类型不匹配。

谁能解释一下这里发生了什么? **array 和 array[m][n] 有什么区别,为什么编译器会报错?

【问题讨论】:

  • 首先,C 没有“2D”数组。它确实有嵌套数组,数组的数组,不幸的是,它们经常被称为多维数组。其次,数组数组与指向指针的指针(有时也称为jagged array)相同。参见例如this old answer of mine 以某种方式直观地表示差异。
  • 为了帮助您更好地理解事物,您需要了解两件事:1) 所有数组(正确的数组)都可以衰减指向它的第一个指针元素。所以如果我们有例如int array[X]; 然后使用普通的array&amp;array[0] 相同,类型为int *;并且 2) 对于任何数组或指针p和索引i,表达式p[i]恰好等于*(p + i),这意味着所有“数组" 索引实际上是指针算法。这两件事有时会使数组和指针看起来很相似。
  • 两者兼有,取决于您询问的对象。二维数组是一种抽象。它只存在于人们的脑海中(细节因人而异)。它不是一种语言结构。无论如何,不​​在 C 中。 int **arrayint array[m][n] 可能会或可能不会在某种程度上实现您首选的抽象。但就 C 而言,它们是不同的、不兼容的东西。
  • for (int i = 0; i &lt; i; i++) { - 您预计i 何时小于i?这个循环会运行吗?鉴于i 出现在循环之前,看起来您的列表本地范围内的i 正在遮蔽外部范围内的i
  • @Chris 我修复了它以使示例更清晰。

标签: c pointers dynamic-memory-allocation


【解决方案1】:

它们是完全不同的东西。

数组是一系列相同类型的值依次存储在内存中。

在 C 中,数组或多或少可以与 指向其第一个元素的指针互换a[0]*a
a[1]*(a+1),等等 —至少当我们谈论一维数组时。

但现在考虑:

int a[3][3];

在这种情况下,a 包含九个元素,在内存中是连续的。 a[0][0]a[0][2],然后紧接着是 a[1][0],直到 a[2][2]

如果您将a 传递给函数,它将适合int *int[3][3]int [][3] 的参数类型(知道第二维的“步幅”对于进行数学运算是绝对必要的)查找给定的元素)。

另一方面:

int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);

在这种情况下,b 是一个包含 3 个元素的数组,每个元素都是一个指向包含 3 个元素的数组的指针。您仍然可以像 b[0]0]b[1][2] 一样访问它,但在幕后正在发生一些完全不同的事情。这些元素并非全部连续存储在内存中,*b 不是其中的任何一个,它是一个指针。如果我们要将b 传递给一个函数,我们会收到带有int **int *[] 类型参数的它。无需提前知道每一行的长度,实际上每一行的长度可能与其他行不同。有些行甚至可以是空指针,它们后面没有整数存储。

【讨论】:

  • 对于您的示例,*aa[0] 相同——您需要 **aa[0][0] 相同。表达式a[1] 非常有意义;它是指向a 的第二个子数组的指针,在大多数情况下会衰减到&amp;a[1][0](指向该子数组的第一个元素的指针)。
猜你喜欢
  • 1970-01-01
  • 2014-12-15
  • 1970-01-01
  • 2012-03-19
  • 2015-12-13
  • 2023-04-10
  • 1970-01-01
  • 2021-05-26
  • 2019-01-09
相关资源
最近更新 更多