我搜索并发现如何在c / c ++'中使用2d数组作为参数。但我遇到了奇怪的事情。
void print2darr3 (int row, int column, int **arr){
int i,j;
for( i = 0; i<row ;i++ ){
for( j=0 ; j<column ;j++ ){
printf("%d ", **(arr++)) ; //printf("%d ", *(arr++)); WORKS WELL.
}
printf("\n");
}
}
int main(void){
int arr[3][3] = {
{10,20,30},
{40,50,60},
{70,80,90}
};
print2darr3(3,3, arr);
return 0;
}
这就是我写的。我打算像这样输出
10 20 30
40 50 60
70 80 90
但我的代码不起作用。
令人惊讶的是,当我在第5行更改了代码printf("%d ", * (arr++));
而不是printf("%d ", ** (arr++));
时,效果很好。
我无法理解这种情况。
因为arr[3][3]
是二维数组,所以我写了int **arr
作为参数。
因此我使用printf("%d ", **(arr++))
打印出每个元素。
为什么只有一个*
在此代码中运行良好?而不是**
?
答案 0 :(得分:4)
作为函数参数传递的数组不会调整到第一个维度之外的指针。您需要将函数标题更改为:
void print2darr3 (int col, int *arr[3]); // removed row because it is known to be 3.
如果您希望函数更通用并且适用于指向指针指向int(或int**
)类型的指针,则需要动态创建数组。这是通过C中的malloc()
/ free()
和C ++中的new
/ delete
来完成的。从技术上讲,你可以在C ++中使用malloc()
,但强烈建议不要这样做。
这是一个示例(对于C,而不是C ++):
int
nrows = 3,
ncols = 3;
int **arr = malloc(nrows * sizeof(int*));
int i;
for(i = 0; i < nrows; ++i) {
arr[i] = malloc(ncols * sizeof(int));
}
// now you can use the arr as a 2D array in your original function
print2darr3(nrows, ncols, arr);
修改强>
正如@Neil在评论中指出的那样,释放你用malloc()
分配的内存很重要。否则,您将创建memory leak。为此,您可以使用free()
。
for(i = 0; i < nrows; ++i) {
free(arr[i]);
}
free(arr);
注意强>
我回答C的原因是因为在我看来,这就是你所使用的。在C ++中,malloc()
的使用不起作用,因为你需要在那里进行显式转换,并且没有C / C ++之类的语言,它们几乎兼容,但不完全兼容。
答案 1 :(得分:2)
C ++解决方案(您标记了)
void print2darr3 (const vector<vector<int>>& arr){
int i,j;
for( i = 0; i<arr.size() ;i++ ){
for( j=0 ; j<arr[i].size() ;j++ ){
printf("%d ", arr[i][j])
}
printf("\n");
}
}
int main(void){
vector<vector<int>> arr = {
{10,20,30},
{40,50,60},
{70,80,90}
};
print2darr3(arr);
}
答案 2 :(得分:1)
如果您有阵列
int arr[3][3];
将其传递给函数意味着第一个维度“衰减”到指针。它只是衰变的第一个维度,因此您需要int **arr
(指向3个元素的数组的指针),而不是int (*arr)[3]
(指向指针的指针或指针数组)。 ,或数组数组,每个数组包含3个元素。)
你可以在其他地方阅读更多内容(我有一个冗长的答案here,它描述了更多,而Question 6.18 of the comp.lang.c FAQ甚至更好),但了解数组/数组之间的区别很重要到数组和指针数组/指针到指针。
答案 3 :(得分:0)
数组不是指针!
它们恰好被自动降级为指向第一个元素的指针。
例如,如果我们有int arr[2]
,那么arr
代表内存中的两个连续的int,它会降级为指向第一个元素的指针(因此它的类型为int*
):
arr ---+ +--- arr + 1
v v
memory: ... | arr[0] | arr[1] | ...
但是如果我们有int arr[2][2]
,那么arr
表示内存中有四个连续的int,它会降级为指向第一个元素的指针(因此它的类型为int (*)[2]
):< / p>
arr ---+ arr + 1 ---+
v v
memory: ... | arr[0][0] | arr[0][1] | arr[1][0] | arr[1][1] | ...
另一方面,如果我们有int *(arr[2])
(为了清晰起见添加了括号),那么arr
表示内存中两个连续int指针的数组,并且它被降级为指向第一个元素(因此它具有类型int**
):
arr ---+ +--- arr + 1
v v
memory: ... | arr[0] | arr[1] | ...
| |
... -+ +- ...
在你的情况下,print2darr3需要类似第三个例子的东西,但你给的东西就像第二个例子。
你可以采取任何一种方式:
#include <stdio.h>
void print2darr3(int rows, int columns, int *arr) {
int i,j;
for (i = 0; i < rows ; i++) {
for (j = 0; j < columns; j++) {
printf("%d ", arr[i * columns + j]);
}
printf("\n");
}
}
int main(void) {
int linear_array[3][3] = {
{10,20,30},
{40,50,60},
{70,80,90},
};
print2darr3(3, 3, (int*)linear_array);
return 0;
}
或者:
#include <stdio.h>
void print2darr3(int rows, int columns, int **arr) {
int i,j;
for (i = 0; i < rows ; i++) {
for (j = 0; j < columns; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main(void) {
int linear_array[3][3] = {
{10,20,30},
{40,50,60},
{70,80,90},
};
int *pointer_array[3] = {
(int*)(linear_array + 0),
(int*)(linear_array + 1),
(int*)(linear_array + 2),
};
print2darr3(3, 3, pointer_array);
return 0;
}
此外,在C(但不是在C ++中),你可以这样做:
#include <stdio.h>
void print2darr3(int rows, int columns, int arr[rows][columns]) {
int i,j;
for (i = 0; i < rows ; i++) {
for (j = 0; j < columns; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main(void) {
int linear_array[3][3] = {
{10,20,30},
{40,50,60},
{70,80,90},
};
print2darr3(3, 3, linear_array);
return 0;
}