为什么我的函数无法使用指针打印多维数组的元素?

Why is my function unable to print an element of a multi-dimensional array using pointers?

本文关键字:数组 元素 打印 指针 函数 我的 为什么      更新时间:2023-10-16

>我有一个 3 X 3 多维数组,我想使用指针打印第 0 行的所有 3 个元素。

这是我编写的代码:

#include <iostream>
void print(int *p){
for(int i = 0; i < 3; i++){
std::cout << (*p)[i];
}
};

int main(void){
int arr[3][3] = {
{1,2,3} ,
{4,5,6} ,
{7,8,9}
};
print(arr);
}

这将引发以下错误:

主.cpp:5:26:错误:下标值不是数组、指针或向量

std::cout << (*p)[i];
~~~~^~

主.cpp:16:4:错误:调用"打印"没有匹配函数

print(arr);
^~~~~

主.cpp:3:6:注意:候选函数不可行:第一个参数没有从"int [3][3]"到"int *"的已知转换

void print(int *p){

据我了解,arr是指向数组第一个元素的指针,该元素本身就是一个数组。那么为什么我找不到指针arr返回的值的数组[i]?

函数print的参数类型为int *

print(int *p)

因此,取消引用表达式中的指针(*p)[i]您将获得类型为int的标量对象。不能将下标运算符应用于类型int的标量对象。

另一方面,在这个电话中

print(arr);

具有int[3][3]类型的参数将转换为指向其第一个元素的指针。数组的元素的类型为int[3]。因此,将数组隐式转换为指向其第一个元素的指针后的表达式类型为int ( * )[3]

错误消息指向此问题

Main.cpp:16:4: error: no matching function for call to 'print'
print(arr);
^~~~~

因为编译器找不到名为 print 的函数,该函数接受类型为int ( * )[3]的参数。

因此,函数print的参数应该声明为:

print( int p[][3] )

print( int ( *p )[3] )

由于数组在函数中没有更改,因此应使用限定符const声明。

在这种情况下,函数定义将如下所示(如果要使用指针(

void print( const int p[][3] )
{
for( const int ( *row )[3] = p; row != p + 3; ++row ) 
{
for ( const int *col = *row; col != *row + 3; ++col )
{
std::cout << *col << ' ';
}
std::cout << 'n';
}
}

这是一个演示程序。

#include <iostream>
void print( const int p[][3] )
{
for( const int ( *row )[3] = p; row != p + 3; ++row ) 
{
for ( const int *col = *row; col != *row + 3; ++col )
{
std::cout << *col << ' ';
}
std::cout << 'n';
}
}
int main() 
{
const size_t N = 3;
int arr[N][N] = 
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr );
return 0;
}

它的输出是

1 2 3 
4 5 6 
7 8 9

然而,这种方法有一个严重的缺点。该函数使用幻数3

最好至少像这样重写函数

#include <iostream>
const size_t N = 3;
void print( const int p[][N], size_t rows )
{
for( const int ( *row )[N] = p; row != p + rows; ++row ) 
{
for ( const int *col = *row; col != *row + N; ++col )
{
std::cout << *col << ' ';
}
std::cout << 'n';
}
}
int main() 
{
int arr[][N] = 
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr, sizeof( arr ) / sizeof( *arr ) );
return 0;
}

您也可以使用默认参数再添加一个参数。例如

std::ostream & print( const int p[][N], size_t rows, std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + rows; ++row ) 
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << 'n';
}
return os;
}

例如

#include <iostream>
const size_t N = 3;
std::ostream & print( const int p[][N], size_t rows, std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + rows; ++row ) 
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << 'n';
}
return os;
}
int main() 
{
int arr[][N] = 
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr, sizeof( arr ) / sizeof( *arr ) ) << 'n';
return 0;
}

最后,您可以编写一个模板函数。

#include <iostream>
template <typename T, size_t N>
std::ostream & print( const T ( &p )[N][N], std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + N; ++row ) 
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << 'n';
}
return os;
}
int main() 
{
const size_t N = 3;
int arr[][N] = 
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr ) << 'n';
return 0;
}

数组的第一个元素arr类型为int[3]。因为所谓的二维数组在语言方面是一个数组的数组

因此arr不能等同于int*,只能等同于int[][3]int(*)[3]

void print(int p[][3]){
for(int i = 0; i < 3; i++){
std::cout << p[0][i];
}
};

void print(int (*p)[3]){
for(int i = 0; i < 3; i++){
std::cout << (*p)[i];
}
};

将是函数的正确签名。任何将多维数组表示为指针的尝试都需要显式强制转换并将其洗回函数中的正确类型,否则将被视为未定义的行为,即使大多数实现都允许这样做。

在我看来,所有以前的答案都没有解决主要问题。

问题是,如何将一个普通的旧 C 数组传递给函数。

如果你想将一个普通的旧C数组传递给一个函数,你有2种可能性。

  • 按引用传递
  • 通过指针传递

看来你想通过引用。但是您使用了错误的语法。

请看:

void function1(int(&m)[3][4])   // For passing array by reference
{}
void function2(int(*m)[3][4])   // For passing array by pointer
{}
int main()
{
int matrix[3][4]; // Define 2 dimensional array
function1(matrix);  // Call by reference
function2(&matrix); // Call via pointer 
return 0;
}

传递给函数的是指向 int 数组的衰减指针。

只需更正语法即可。

附加提示:

不要在C++中使用纯 C 样式数组。从不。请使用 STL 容器。