use*_*312 5 c pointers multidimensional-array
如果可能的话:
MyFunction(int *array, int size)
{
for(int i=0 ; i<size ; i++)
{
printf(“%d”, array[i]);
}
}
main()
{
int array[6] = {0, 1, 2, 3, 4, 5};
MyFunction(array, 6);
}
Run Code Online (Sandbox Code Playgroud)
为什么以下不是?
MyFunction(int **array, int row, int col)
{
for(int i=0 ; i<row ; i++)
{
for(int j=0 ; j<col ; j++)
{
printf(“%d”, array[i][j]);
}
}
}
main()
{
int array[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
MyFunction(array, 3, 3);
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*ode 13
首先,一些标准语言:
6.3.2.1左值,数组和函数指示符
...
3除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则表达式的类型为"数组类型" "转换为类型为"指向类型的指针"的表达式,该表达式指向数组对象的初始元素,而不是左值.如果数组对象具有寄存器存储类,则行为未定义.
鉴于声明
int myarray[3][3];
Run Code Online (Sandbox Code Playgroud)
该类型的myarray是"的3元素数组的3元素数组int".按照上面的规则,当你写作时
MyFunction(myarray, 3, 3);
Run Code Online (Sandbox Code Playgroud)
的表达 myarray具有从"3元素数组的3元素数组其类型隐式转换("衰变")int到"指针3元素数组的" int",或int (*)[3].
因此,您的函数原型需要
int MyFunction(int (*array)[3], int row, int col)
Run Code Online (Sandbox Code Playgroud)
请注意,int **array是不一样的int (*array)[3]; 指针算术会有所不同,所以你的下标不会指向正确的位置.请记住,数组索引是根据指针算法定义的:a[i]== *(a+i), a[i][j] == *(*(a + i) + j). a+i将产生不同的值取决于a是a int **还是an int (*)[N].
这个特殊的例子假设你总是传递一个Nx3元素数组int; 如果你想处理任何NxM大小的数组,那就不是非常灵活.解决此问题的一种方法是显式传递数组中第一个元素的地址,因此您只需传递一个简单的指针,然后手动计算正确的偏移量:
void MyFunction(int *arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", a[i*col+j]);
}
int main(void)
{
int myarray[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
...
MyFunction(&myarray[0][0], 3, 3);
Run Code Online (Sandbox Code Playgroud)
由于我们传递一个简单的指针int,我们不能使用双下标MyFunc; 结果arr[i]是整数,而不是指针,所以我们必须在一个下标操作中计算数组的完整偏移量.请注意,此技巧仅适用于真正的多维数组.
现在,a ** 可以指示以二维结构组织的值,但是以不同方式构建的值.例如:
void AnotherFunc(int **arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", arr[i][j]);
}
int main(void)
{
int d0[3] = {1, 2, 3};
int d1[3] = {4, 5, 6};
int d2[3] = {7, 8, 9};
int *a[3] = {d0, d1, d2};
AnotherFunc(a, 3, 3);
...
}
Run Code Online (Sandbox Code Playgroud)
按照上面的规则,当表达式d0,d1和d2出现在初始化器中时a,它们的类型都是从"3元素数组int"转换为"指向int".类似地,当表达式a出现在调用中时AnotherFunc,其类型将从"指针的3元素数组int"转换为"指向指针的指针int".
请注意,在AnotherFunc我们下标两个维度而不是像我们所做的那样计算偏移量MyFunc.那是因为a是一个指针值数组.表达式arr[i]使我们得到第i个指针值偏离该位置arr; 然后我们找到该指针值的第j个整数值偏移量.
下表可能有所帮助 - 它显示了各种数组表达式的类型以及它们根据声明衰减的内容(T (*)[N]是指针类型,而不是数组类型,所以它不会衰减):
Declaration Expression Type Implicitly Converted (Decays) to
----------- ---------- ---- --------------------------------
T a[N] a T [N] T *
&a T (*)[N]
*a T
a[i] T
T a[M][N] a T [M][N] T (*)[N]
&a T (*)[M][N]
*a T [N] T *
a[i] T [N] T *
&a[i] T (*)[N]
*a[i] T
a[i][j] T
T a[L][M][N] a T [L][M][N] T (*)[M][N]
&a T (*)[L][M][N]
*a T [M][N] T (*)[N]
a[i] T [M][N] T (*)[N]
&a[i] T (*)[M][N]
*a[i] T [N] T *
a[i][j] T [N] T *
&a[i][j] T (*)[N]
*a[i][j] T
a[i][j][k] T
高维数组的模式应该清晰.
编辑:这是我尝试根据您的新示例代码提出的更为重要的答案:
不论阵列的尺寸,你通过什么是"指向数组的指针" -它只是一个单一的指针,但指针的类型可以改变.
在您的第一个示例中,int array[6]是一个包含6个int元素的数组.传递array将指针传递给第一个元素,这是一个int,因此参数类型是int *,可以等效地写为int [].
在第二个示例中,int array[3][3]是一个包含3行(元素)的3行(元素)数组int.传递array将指针传递给第一个元素,该int元素是一个3 秒的数组.因此,类型是int (*)[3]- 指向3个元素的数组的指针,可以等效地写为int [][3].
我希望你现在看到差异.传递时int **,它实际上是指向int *s 数组的指针,而不是指向2D数组的指针.
实际的一个例子int **是这样的:
int a[3] = { 1, 2, 3 };
int b[3] = { 4, 5, 6 };
int c[3] = { 7, 8, 9 };
int *array[3] = { a, b, c };
Run Code Online (Sandbox Code Playgroud)
这array是一个3 int *s 的数组,并将此作为参数传递将导致int **.
原始答案:
您的第一个示例实际上不是2D数组,尽管它以类似的方式使用.在那里,你创建了ROWS许多char *指针,每个指针都指向不同的COLS字符数组.这里有两个间接层次.
第二个和第三个示例实际上是2D数组,其中整个ROWS * COLS字符的内存是连续的.这里只有一个间接层.指向2D数组的指针不是char **,但是char (*)[COLS],您可以这样做:
char (*p)[SIZE] = arr;
// use p like arr, eg. p[1][2]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1952 次 |
| 最近记录: |