我一直在试图理解这两个定义之间的区别,以及如何正确地使用它们。
在我看来,用arr[length][width]
定义2d数组将矩阵的内容依次存储在一个接一个的内存中(矩阵基本上是一个大行),这样您就可以以这样的方式访问i,j坐标中的数字:*(arr+width*i+j)
。当将它发送到一个函数时,声明可以是func(int *arr)
,访问矩阵内容没有问题,因为2d数组是如何在内存中表示的。
然而,将数组定义为int *arr[];
似乎并没有以相同的线性、连续的方式将矩阵的内容存储在内存中。函数的声明必须是func(int **arr)
或(int *arr[])
。虽然你仍然可以像这样通过坐标i,j来访问矩阵:arr[i][j]
,但这样做似乎是不可能的:*(arr+width*i+j)
。我是否认为它是正确的,因为用这种方式定义2d矩阵不会连续地将矩阵的行存储在内存中,还是我遗漏了什么?
发布于 2022-05-31 09:08:46
这声明了一个2D数组:
int arr1[100][200];
这声明了一个一维指针数组:
int *arr2[100];
它们不是一回事。arr1包含20000个ints,arr2包含100个指针。
arr120将计算第21行、第31列的地址,并直接到那里去。arr220将计算第21指针的地址,读取指针,在指针指向的位置之外计算出地址30 int (因此,31 int,如果它指向一个int数组),然后转到那里。
如果愿意,您可以为20000个ints分配空间,并且可以保存指向arr2中每一行的指针。然后,两者都可用于将数字存储在行和列中。
arr2的优点在于,因为每一行都有一个指向实际数据的指针,所以可以有不同大小的行、重叠行或缺失行。在arr1中,行正好有200个In长,没有例外。arr2的缺点是计算机必须做更多不需要做的工作,也就是速度更慢。arr2的另一个缺点是,您仍然需要有一个位置来放置ints,所以如果您的问题是要找到放置ints的位置,那么arr2实际上并不能解决这个问题。
发布于 2022-05-31 09:14:22
声明意味着不同的事情。即使您可以通过相同的语法访问(读/写)一个整数,因为x[y]
等同于*(x + y)
。
int *a[]
是一个一维指针数组。
每个指针可以(但不一定)指向一个一维整数数组。它也可以是空指针,也可以是指向单个整数的指针。
如果所有指针指向整数的一维数组,则这些数组可以是不同大小的。
每个一维数组( a
作为指针数组和指针指向的每个整数数组)都在内存中连续地拥有其所有元素。但这些一维阵列的位置是任意的。
int a[][]
是一个二维整数数组。
所有整数在内存中都是连续的。
发布于 2022-05-31 09:14:26
如果你有这样的数组
int arr[length][width];
然后,这个表达式*(arr+width*i+j)
访问数组的元素是不正确的,至少因为表达式的类型是int[width]
而不是int
,而且一般来说,当至少i
不等于0时,将访问数组之外的内存。
要访问数组的元素,必须使用以下表达式*( *( arr + i ) + j )
。
处理数组的函数可以通过以下方式声明
void f( size_t, size_t, arr[*][*] );
或使声明更具可读性,如
void f( size_t rows, size_t cols, arr[][cols] );
至于这个数组
int * arr[length];
这是一个一维数组,每个元素依次指向一个单独的一维数组,然后可以使用相同的表达式*( *( arr + i ) + j )
访问数组arr[i][j]
的元素。这是因为下标运算符是由这个公式*( *( arr + i ) + j )
计算的。
相应的函数可以声明如下
void f( int * arr[], size_t rows, size_t cols );
https://stackoverflow.com/questions/72444791
复制相似问题