- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
给定以下两个声明,有什么区别?
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 时,这些声明在实际应用中是相同的。技术差异包括:
b
生成计算数组元素位置的代码,除非它能够推断出 b 的值
在编译时通过查看程序中的其他代码。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/
我是一名优秀的程序员,十分优秀!