我用FORTRAN
编程,但我决定学习C
和C++
。我从C
语言开始,我从未使用的一件事是指针,因为FORTRAN
通过引用传递值。我构建了下面的示例代码,以了解指针如何与多维数组一起使用:
#include <stdio.h>
#include <stdlib.h>
#define DIM1 3
#define DIM2 2
#define DIM3 4
void display3DArray1(int, int , int n, int (*arr)[][n]);
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]);
int main(void)
{
int matrix3D[DIM1][DIM2][DIM3] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
int (*pmatrix3D)[DIM2][DIM3] = matrix3D;
display3DArray1(DIM1, DIM2, DIM3,pmatrix3D);
display3DArray2(DIM1, DIM2, DIM3,pmatrix3D);
return 0;
}
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
}
}
}
}
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
}
}
}
}
代码有效,但有些东西我无法理解。当我尝试在第一个函数中使用第二个函数的第二个printf
时,我得到一个编译错误:
&#34;无效使用带有未指定范围的数组&#34; - 在gcc下。
为什么*(arr + i)
在第一个函数中不起作用?
答案 0 :(得分:2)
您可以使用以下两种方式传递/打印矩阵:
void display3DArray1(int rows, int cols1, int cols2, int *A) {
int *a, i, j, k;
printf("\n");
for(i=0; i<rows; i++) {
for(j=0; j<cols1; j++) {
for(k=0; k<cols2; k++) {
a= A+(i*cols1*cols2)+(j*cols2)+k;
printf("%d, %p\n", *a, a);
}
}
}
}
void display3DArray2(int A[DIM1][DIM2][DIM3]) {
int i, j, k;
printf("\n");
for(i=0; i<DIM1; i++) {
for(j=0; j<DIM2; j++) {
for(k=0; k<DIM3; k++) {
printf("%d, %p\n", A[i][j][k], &A[i][j][k]);
}
}
}
}
第一种方法不依赖于矩阵的维数;第二个。因此,第一个需要显式地址计算(行 i ,col j ,单元格 k )。
分别使用电话:
display3DArray1(DIM1, DIM2, DIM3, (int *)matrix3D);
display3DArray2(matrix3D);
注意矩阵的转换为int指针。
在您的代码中,您使用参数名称来指定矩阵的尺寸。在我的C版本中,这是不合法的;它们必须是常量。
答案 1 :(得分:2)
只是Paul Ogilvie回答的补充。
可变长度数组的正确用法是:
void display3DArray3(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", arr[i][j][k], &arr[i][j][k]);
}
}
}
}
答案 2 :(得分:1)
f(T arr[])
这样的函数参数声明声明了一个不完整的类型,其大小未知(无论是在编译时还是在运行时)。最初我认为函数参数声明中的空方括号只是声明一个指针 - 尽管符号 - 但是情况并非如此。该参数仍然具有数组类型,尽管不完整。 1
写作时
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2])
你将指针声明为这种不完整类型的未知大小。这个指针不能以通常的方式操纵;特别是,为了跳转到下一个元素而添加它是不可能的,因为我们不知道当前元素的结束位置(因此下一个元素开始)。但你在
尝试printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
最里面的arr+1
。只需解除引用即可,因为该变量可以保存第一个元素的地址。这就是第一个函数中的print:
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
*arr
。已知arr
点的不完整数组的元素大小(这些元素是cols2
整数的数组),以便我们可以添加到*arr
,即使我们无法正确添加arr
。
为了完整性:为什么你可以在第二个函数中以这种方式访问arr
?好吧:
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2])
将arr
声明为不完整的数组类型,为true;但其元素的大小是众所周知的:那些是cols1 x cols2 int矩阵。声明并没有说明有多少,但如果我们知道何时停止,我们肯定可以迭代它们。
答案 3 :(得分:0)
我很难找到用于解引用rank2和rank3矩阵的正确语法。目的是删除索引级别以加快执行速度。这是一些伪代码,可以帮助您入门。这更多是关于正确使用语法(MSVC 2019),而不是工作代码示例。
int recurse(int n, unsigned char rank2[13][4], unsigned char rank3[13][4][13])
{
if (n < 13)
{
unsigned char (*deRefRank1)[4] = &rank2[n]; // deref matrix rank 2 to rank 1
unsigned char(*deRefRank2)[4][13] = &rank3[n]; // deref matrix rank 3 to 2
// insert pre-recurse code here ... use (*deRefRank1)[] and (*deRefRank2)[][]
if (recurse(n + 1, rank2[n], rank3[n])
return -1;
// insert post-recurse code here ...
}
return 0;
}
答案 4 :(得分:-2)
“print”例程中的数组索引无效。 'matrix3D'的声明暗示该名称的类型是'指向int的指针'。注意:那里只有一个间接层。索引表达式在术语前面有一堆'' - s;在C中,这意味着''/ / em>'右边的项是一个指针,必须取消引用才能获得值'。这意味着你实际上将'matrix3D'视为'指向(指向int的指针)'的指针,这是太多的间接。