Dov*_*iin 3 c arrays pointers multidimensional-array
我正在学习大学课程中的C和指针,我认为除了多维数组和指针之间的相似性之外,我对这个概念有很好的把握.
我认为,因为所有数组(甚至是多维数组)都存储在连续的内存中,你可以安全地将其转换为a int*(假设给定的数组是int[].)但是,我的教授说定义中的星数取决于数字数组中的维度.所以,一个int[]会变成一个int*,一个int[][]会成为一个int**,等等.
所以我写了一个小程序来测试这个:
void foo(int** ptr)
{
}
void bar(int* ptr)
{
}
int main()
{
int arr[3][4];
foo(arr);
bar(arr);
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,编译器在两个函数调用上发出警告.
main.c:22:9: warning: incompatible pointer types passing 'int [3][4]' to parameter of type
'int **' [-Wincompatible-pointer-types]
foo(arr);
^~~
main.c:8:16: note: passing argument to parameter 'ptr' here
void foo(int** ptr)
^
main.c:23:9: warning: incompatible pointer types passing 'int [3][4]' to parameter of type
'int *' [-Wincompatible-pointer-types]
bar(arr);
^~~
main.c:13:15: note: passing argument to parameter 'ptr' here
void bar(int* ptr)
^
2 warnings generated.
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?你怎么能改变函数调用,所以其中一个会接受数组?
我的原始问题被标记为重复,因为我无法弄清楚如何删除重复,我再次问它.
编辑:这不是如何将多维数组传递给C和C++中的函数的重复,因为我问的是如何更改函数调用本身,而不是函数签名.我知道其中一个功能是正确的,我只是不确定你会选择哪一个或如何调用它.
编辑2:这是我原来的问题的副本,但原件被错误地标记为重复,无法得到答案所以我重新问了它.
但是,我的教授说定义中的星数取决于数组中的维数.所以,一个
int[]会变成一个int*,一个int[][]会成为一个int**,等等.
我真的,真的希望你只是误解了他在说什么,因为这不正确.
除非它是sizeof或一元运算&符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型为" N-element array of T" 的表达式将被转换("decay")为类型的表达式"指向T",表达式的值将是数组第一个元素的地址.如果T是数组类型,则最后使用指向数组的指针,而不是指向指针的指针.
通过一些例子:
int arr[10];
...
foo( arr, 10 ); // need to pass number of rows as a separate parameter
Run Code Online (Sandbox Code Playgroud)
在调用中foo,表达式的arr类型为"10-element array of int".因为它不是sizeof或一元运算&符的操作数,所以它"衰减"到类型int *,表达式的值将是第一个元素的地址.因此,原型foo将是
void foo( int *arr, size_t rows ); // or int arr[]; it means the same thing in this context
Run Code Online (Sandbox Code Playgroud)
请注意,这与表达式的结果类型相同&arr[0].arr[0]是一个int对象,所以&arr[0]给我们一个int *.我,arr == &arr[0].
到现在为止还挺好.现在让我们看一下2D数组:
int arr[10][20];
...
foo( arr, 10 );
Run Code Online (Sandbox Code Playgroud)
在这种情况下,表达式arr具有" 20元素数组的int 10 元素数组 "; 它"衰减"到"指向20个元素数组的int指针"类型的表达式; 因此,原型foo变为
void foo( int (*arr)[20], size_t rows ); // or int arr[][20]
Run Code Online (Sandbox Code Playgroud)
还记得上面所说的"除非是......一元&算子的操作数"吗?如果我们写&arr[0],arr[0]具有类型"的20个元素的阵列int",但它并不能自动地衰减到一个指针.因此int **,我们得到一个类型的表达式,而不是获得类型的表达式int (*)[20].再说一遍arr == &arr[0].
现在让我们看一下3D数组:
int arr[10][20][30];
...
foo( arr, 10 );
Run Code Online (Sandbox Code Playgroud)
这次,表达式arr具有" 30int元素阵列的20元素数组的10元素数组 ".这一次,它"衰变"为" 30元素数组的20元素数组的int指针"类型的表达式,原型现在是
void foo( int (*arr)[20][30], size_t rows ); // or int arr[][20][30]
Run Code Online (Sandbox Code Playgroud)
再一次,arr[0]有一个数组类型,所以表达式&arr[0]给了我们类型int (*)[20][30]; 再次,arr == &arr[0].
从现在开始,高维数组的模式应该是清晰的.
现在,这带来了一个小问题.指向N-element数组的指针与指向-element数组的指针的类型不同M,其中N != M.如果您的函数原型是
void foo( int (*)[20], size_t rows );
Run Code Online (Sandbox Code Playgroud)
那么它只适用于Nx20阵列; 你不能将指针传递给具有不同外部维度的数组:
void foo( int (*ap)[20], size_t rows );
...
int arr1[10][20];
int arr2[20][20];
int arr3[20][30];
foo( arr1, 10 ); // okay
foo( arr2, 20 ); // okay
foo( arr3, 20 ); // not okay - arr3 has type int (*)[30], which is not *compatible*
// with int (*)[20]
Run Code Online (Sandbox Code Playgroud)
编辑
在函数期望a int *并且你有一个多维数组的情况下,你明确地将指针传递给第一个元素:
void foo( int *, size_t size );
...
int arr2[10][20];
int arr3[20][10][5];
foo( &arr2[0][0], sizeof arr2 / sizeof arr2[0][0] );
foo( &arr3[0][0][0], sizeof arr3 / sizeof arr3[0][0][0] );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2659 次 |
| 最近记录: |