**运算符不能将二维数组作为参数
**operator does not work on 2-dimensional array as parameter
我搜索并发现'如何在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++))
打印出每个元素。
为什么只有一个*
在这段代码中工作得很好?而不是**
?
作为函数参数传递的数组不能调整为第一维以外的指针。您需要将函数头更改为:
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()
分配的内存是很重要的。否则,您将创建内存泄漏。为了做到这一点,您可以使用free()
.
for(i = 0; i < nrows; ++i) {
free(arr[i]);
}
free(arr);
注意
我选C的原因是因为在我看来你用的是C。在c++中,malloc()
的这种使用将不起作用,因为您需要在那里进行显式强制转换,并且没有C/c++这样的语言,它们几乎兼容,但不是完全兼容。
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);
}
如果你有一个数组
int arr[3][3];
传递给函数意味着第一个维度"衰减"为指针。它只是第一个维度会衰减,所以你想要的参数不是int **arr
(指向指针的指针,或者指针的数组),而是int (*arr)[3]
(指向包含3个元素的数组的指针,或者数组的数组,每个数组包含3个元素)。
您可以在其他地方阅读更多内容(我在这里有一个很长的答案,描述了更多内容,comp.lang.c FAQ的问题6.18甚至更好),但是理解数组的数组/指针到数组的数组和指针的数组/指针到指针的数组之间的区别是很重要的。
数组不是指针!
它们恰好被自动降级为指向第一个元素的指针。
例如,如果我们有int arr[2]
,那么arr
在内存中表示两个连续的整数,并且它被降级为指向第一个元素的指针(因此它的类型为int*
):
arr ---+ +--- arr + 1
v v
memory: ... | arr[0] | arr[1] | ...
但是如果我们有int arr[2][2]
,那么arr
代表内存中四个连续的整数,它被降级为指向第一个元素的指针(所以它的类型是int (*)[2]
):
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;
}
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- 运算符重载:"operator+"必须采用零个或一个参数
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- 参数相关查找和流运算符重载
- C++:使用运算符 = 调用多参数构造函数
- 了解布尔运算符==(参数 1,参数 2)
- 我能否根据其运算符()的签名专门化可变参数模板参数
- SFINAE 检查模板参数运算符
- 不允许运算符 const 参数调用 const 成员函数
- 为私有结构定义双参数运算符重载
- C++ 通过自定义赋值运算符隐式转换函数参数
- 函数参数变量总是需要 & 或 * 运算符吗?
- 有条件地将默认参数传递给函数(使用"?"运算符)
- 可变参数模板参数转发使用逗号运算符
- C++函数,它将数组、谓词和运算符作为参数,并将运算符应用于满足谓词的数组元素
- 具有两个或多个模板参数的 C++ assigment 运算符
- 将多个参数传递给运算符 []
- 如何使用类的参数重载运算符+?
- 不允许在C++中使用多参数运算符 [] 的根本原因