二维数组作为函数的参数传递

作者:@houkai
本文为作者原创,转载请注明出处:https://www.cnblogs.com/houkai/p/3568408.html


如何将二维数组作为函数的参数传递,这是涉及到多维数组时经常要遇到的问题。长期来,我们往往知其然,但不知其所以然。这里简单总结一下。

1.《C程序设计》中讲到:可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如:

void Func(int array[3][10]);
void Func(int array[][10]);

二者都是合法而且等价,但是不能把第二维或者更高维的大小省略。两个示例程序如下:

复制代码
#include <iostream>
using namespace std;
void fun(int a[2][2],int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<a[i][j]<<endl;
        }
    }
}

void main() {
    int test[2][2]={{1,2},{3,4}};
    fun(test, 2);
    cin.get();
}
复制代码

上面程序提供了二维数组中两个维度的大小,再看下面:

复制代码
#include <iostream>
using namespace std;
void fun(int a[][2],int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<a[i][j]<<endl;
        }
    }
}

void main() {
    int test[2][2]={{1,2},{3,4}};
    fun(test, 2);
    cin.get();
}
复制代码

上述两段程序均可正常运行,输出结果:

QQ图片20140225220050

为什么必须要提供第二维度的大小呢?因为编译阶段,编译器要为a[i][j]正确寻址。a[i][j]的地址为:a+i*列数(第二维大小)+j。

2.如果在函数参数中传入二维指针int **,二维指针中包含了a、a[0]/a[1]、数据三层结构。

image

int**已经提供了a[0]及a[1]的地址,这样在对a[i][j]寻址的过程中,就不需要第二维大小来确定a+i*列数(第二维大小)了。程序如下:

复制代码
#include <iostream>
using namespace std;

void fun(int **a,int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<a[i][j]<<endl;
        }
    }
}

void main() {
    int **test = new int*[2];
    for(int i=0;i<2;i++)
    {
        test[i] = new int[2];
    }
    test[0][0] = 1;test[0][1] = 2;test[1][0] = 3;test[1][1] = 4;
    fun(test, 2);

    cin.get();
}
复制代码

3.如果把二维数组名传递给int**,编译阶段将会报错:不能将参数 1 从“int [2][2]”转换为“int **。因为二维数组的结构和二维指针是不同的,在底层,二维数组的结构和一维数组是一样的。在二维数组中,a和a[0]均指向数组首地址,而且二维数组是按行顺序存储的。

image

所以说二维数组和二维指针是大大不同的,二维数组的结构基本和一维数组是一样的。这样,把二维数组传递给int**的程序也就不难理解了,如下:

复制代码
#include <iostream>
using namespace std;

void fun(int **a,int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<*((int*)a+i*n+j)<<endl;//二维数组a结构实质就是一维数组
            //传入时强制转化为int**,底层变成了两层指针结构是错误的,这里要强制转化为一层结构
            //由于强制转换的int** 是错误的,所以不能把它当做二维指针来用,不能使用a[i][j]
        }
    }
}

void main() {
    int test[2][2]={{1,2},{3,4}};
    fun((int **)test, 2);
    cin.get();
}
复制代码

我的理解大致就是这样了。

posted @   侯凯  阅读(2627)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示