该函数应该作为参数得到int.so函数签名的二维方阵:
void f (int** arr,int n) // n is a size of each dimension
我已经定义了数组:
int arr [][5] = {{0,1,1,1,1},{1,1,1,1,1},{0,1,1,0,1},{0,1,1,1,1},{0,1,1,1,0}}
致电:func (arr,5); //<- compilation error
也func ((int**) arr,5); //<- runtime error (*arr == NULL)
我应该怎么做呢?
答案 0 :(得分:3)
int**
与您声明的内容之间存在细微差别,这就是您无法将它们相互投射的原因。
这应该适合你:
void f (int arr[][5],int n)
问题是当你在函数体中编写arr[i][j]
时,需要将两个索引转换为指向内存的指针。因此,您需要第二个维度,因为计算始终为arr[i][j] = arr + i * dimen + j
。
答案 1 :(得分:1)
声明该函数采用锯齿状数组,即每个行中可能有不同大小的数组。
void f (int** arr,int n)
需要以不同的方式创建这样的数组 - 您需要分配n
个指针,然后为每个数组行分配一个单独的内存块:
int **arr = malloc(sizeof(int*)*n);
for (int i = 0; i != n ; i++) {
// This code uses the same size for each row, but jagged arrays
// are free of the "rectangular array" limitations.
arr[i] = malloc(sizeof(int)*n);
}
使用这样的数组后,在释放数组之前释放它的行:
for (int i = 0; i != n ; i++) {
free(arr[i]);
}
free(arr);
你能解释一下我为什么做的不正确吗?
你所做的不正确的原因是你向一个需要锯齿状数组的函数提出一个矩形数组。两者具有非常不同的内存结构。
静态初始化的矩形数组是一个大小为25*sizeof(int)
的单个连续内存块。通过编译器知道第二维具有五个元素,将“第二维”添加到该平坦的内存块中。这就是编译器如何将“cookie cutter”应用到块中,将其划分为五个相等的五个整数块。访问(i,j)
处的元素将转换为将5*i+j
偏移量添加到arr
的基址(单指针解除引用)。
另一方面,锯齿状数组是指向数组的指针数组。它的大小为5*sizeof(int*)
。这些指针中的每一个都可以指向一个单独的数组。访问(i,j)
处的元素将转换为访问arr[i]
指针,然后访问从该值获取的偏移量处的值(两个指针解引用)。
答案 2 :(得分:1)
我建议使用保存二维数据的一维数组。这使得处理和传递数组变得更加容易,而且在我看来并不难理解......
void f (int* arr, int n) // n is a size of each dimension
int arr [25] = {0,1,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1,1,0};
在你的函数中你可以像这样遍历数据:
...
for (int row = 0; row < n; ++row)
{
for (int col = 0; col < n; ++col)
{
arr[row*n + col] = 1; // or something else...
}
}