gpt4 book ai didi

c - 参数c[a][b]和c[][2]有什么区别

转载 作者:太空宇宙 更新时间:2023-11-04 01:18:15 24 4
gpt4 key购买 nike

给定以下两个声明,有什么区别?

int foo ( int a, int b, int c[a][b] ) {
int foo ( int a, int b, int c[][2] ) {

我知道最上面的语句是“可变长度数组”(VLA),但我不确定我是否理解这意味着什么。这两者产生相同的结果。

int foo ( int a, int b, int c[a][b] ) {
for ( int *p = c[0]; p <= &(c[a-1][b-1]); p++ ) {
*p = 0;
}
}

对比..

int foo ( int a, int b, int c[][2] ) {
for ( int *p = c[0]; p <= &(c[a-1][b-1]); p++ ) {
*p = 0;
}
}

这是我的主要

int main () {
int m[2][2] = { {1,2},{3,4} };
foo(2,2,m);
printf( "%s %d %d %d %d", "foo", m[0][0],m[0][1],m[1][0],m[1][1] );
return 0;
}

我找不到任何资源来充分解释这里发生的事情。

最佳答案

int foo ( int a, int b, int c[a][b] )中,参数c被声明为指向数组的指针b 整数。即指向一个int数组,其中元素个数为b

int foo ( int a, int b, int c[][2] )中,参数c被声明为一个指向2数组的指针int.

b 为 2 时,这些声明在实际应用中是相同的。技术差异包括:

  • 在后面的声明中,编译器知道数组有两个元素,它可以生成内置有 2 的代码。在前一个声明中,编译器无法仅从声明中知道数组有多大。因此,当它出于某种原因需要数组大小时,它必须在运行时使用 b 生成计算数组元素位置的代码,除非它能够推断出 b 的值 在编译时通过查看程序中的其他代码。
  • 在后面的声明中,C 标准并不清楚a 是否被求值。在 a 是一个简单对象的情况下,这无关紧要,但您也可以将表达式放在那里,并且表达式可以导致可观察到的效果,例如打印输出。我见过一个确实评估该维度的 C 实现和一个没有评估该维度的 C 实现。我从未见过现实世界的程序如此重要。

当参数声明以数组形式出现时,第一维自动调整为指针。这是因为 C 仅通过指向第一个元素来传递数组,而不是像传递非数组参数那样传递整个数组的值。因此声明为 int foo[a][b][c][d] 的参数被调整为 int (*foo)[b][c][d] .只调整了第一个维度,因为指针确实指向内存中的实际数组,所以其他维度都在那里;它们不是指针。允许以这种方式声明参数只是为了符号上的方便。

在这两种情况下,c 都是指向int 数组的指针。通常,这样的参数指向第一个 int 数组,该数组后跟另一个,另一个,依此类推,以形成 int 数组的数组.这是第二个维度,b 或 2,很重要。编译器需要那个维度来知道 int 的数组有多大,这样,当源代码访问第一个数组以外的数组时,编译器能够通过将每个数组的大小相乘来计算它们的地址int 数组索引。在 2 的情况下,数组大小是常量,编译器应该生成与常量的乘积。在 b 的情况下,编译器可能必须生成从寄存器或某处获取 b 并乘以它的代码。

如果foo写成always取2个int的数组,那么你应该用2声明参数。如果 foo 被编写为接受调用者请求的任何大小的数组,那么您应该使用 b 声明参数。

关于c - 参数c[a][b]和c[][2]有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51796521/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com