【问题标题】:Strange parameter recuperation of an array数组的奇怪参数恢复
【发布时间】:2017-06-25 09:59:51
【问题描述】:

我试图理解一些将多维数组传递给函数的代码。但是这个函数的原型让我很感兴趣。

程序创建这个“选项卡”变量:

#define N 8

float tab[N][N];
tab[0][0] = 2; tab[0][1] = 3; tab[0][2] = -1;
tab[1][0] = 3; tab[1][1] = 1; tab[1][2] = -4;
tab[2][0] = 1; tab[2][1] = 2; tab[2][2] =  3;
hello(tab);

我们有这个功能:

function hello(float mat[][N]) {

我不明白为什么 hello 函数使用空 [] 然后使用 [N] 获取 tab 变量。它有什么变化?我不明白...为什么不 tab[][] ?

代码似乎是由优秀的开发人员编写的,所以我不认为 N​​ 变量是无缘无故的。

如果你能解释一下,谢谢你的时间!

The original code

【问题讨论】:

  • 大约一半的答案在这里:stackoverflow.com/questions/1461432/what-is-array-decaying。从中可以推断出后半部分:当数组衰减时,第一个维度的大小会丢失。
  • 我应该改写我的评论。大小不一定丢失。它可能会被丢弃。 float mat[][N] 选择丢弃并成为一个指向未知长度数组的指针N
  • @user4581301 感谢您的回答。您提供给我的 stackoverflow 答案对于我来说有点高水平。我虽然数组的第一维包含第二维每个冒号的起始点的地址。如果我松开我的第一个维度的大小,那么我怎么能安全地到达我的第二个维度而不离开数组和段错误!?
  • @user4581301 好的,但这不会改变如果我无法安全访问我的第一个维度,我也无法访问第二个维度?
  • 假设你是编译器,看到void hello(float mat[][]) { use(mat[1][1]); } 如果你不知道数组有多少列,你如何计算mat[1][1] 的内存位置?

标签: c++ c function multidimensional-array


【解决方案1】:
float tab[N][N];

通过N 定义N 的数组。我不会使用行或列,因为数组如何面向程序逻辑可能与数组在内存中的表示方式无关。只要知道这将是一块 N*N 长的内存块,可以使用mat[0..N-1][0..N-1] 访问。尺寸是已知的且恒定的。当你定义一个数组时,它必须知道它的大小并且这个大小不能改变。如果您不知道大小,请使用std::vectorstd::vector<std::vector<YOUR TYPE HERE>>

float tab[][];

是非法的,因为数组的大小是未知的。编译器不知道要为数组分配多少存储空间,也无法生成功能正常(即使有缺陷)的程序。

当您将数组传递给诸如

之类的函数时
function hello(float mat[][N])

数组衰减为指针。更多信息:What is array decaying? 一旦数组衰减,第一个维度的大小就会丢失。要安全地使用数组,您必须已经知道数组的大小或将其作为另一个参数提供。示例:

function hello(float mat[][N], size_t matLen)

有问题,大小为N。你知道它是N,你可以放心地拨打电话

hello(mat);

不提供任何大小,只需在函数内使用N 作为边界。 N 不是一个狡猾的magic number,但它可以被赋予一个更具描述性的名称。

你也可以完全明确和

function hello(float mat[N][N])

并消除任何歧义以及将函数与大小为 M × N 的数组一起使用的能力。有时这是值得做出的权衡。

【讨论】:

  • 这个参数声明float *mat[N],不等价于float mat[][N],
  • @VladfromMoscow 同意。它不是。我在那里做错了什么。
  • 感谢您的回答。我现在明白了。它只是为了让编译器工作的最小符号!
【解决方案2】:

让我稍微“非技术性地”解释一下,但可能是全面的:

float tab[ROW][COL] 视为一个二维浮点数组,其中“ROW”代表行,“COL”代表列,并认为该数组一个完整的行依次映射到内存,即

r0c0,r0c1,r0c2
r1c0,r1c1,r1c2
r2c0,r2c1,r2c2

对于ROW=3COL=3。然后,如果编译器必须找出写入tab[2][1] 的位置,则它必须占用行大小的2 倍+ 1(其中行大小实际上是列数COL)。因此,对于一个单元格寻址,知道行的大​​小是相关的,而在一行内只需添加列索引。因此,像tab[][N] 这样的声明就足够了,因为N 定义了列数——即行的大小——并让编译器正确地处理每个单元格。

希望能有所帮助。

【讨论】:

  • 感谢您的回答。如果我做对了,编译器就不需要在第一个 [] 中传递多少行的信息!好的......所以它不会改变数组的内容吗?它只是一个简化?
  • @Doctor:是的,它不会改变数组的内容。如果是简化或抽象,我不能说:如果类型是tab[][N],你可以传入任何带有N 列的数组,不管这个数组有多少行。如果 type 是 tab[R][C],那么你可以只传入包含 C 列和 R 行的数组。
猜你喜欢
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 2016-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多