zoukankan      html  css  js  c++  java
  • 二维数组作为函数的参数传递

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

    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();
    }

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

  • 相关阅读:
    Asp.net 动态添加Meta标签
    【转】在SharePoint Server 2010中更改“我的网站”
    SPQuery DateTime 类型查询
    Asp.net Web Application 打开 SharePoint 2010 Site 错误 The Web application at could not be found
    How To Create SharePoint 2010 Site Collection In Its Own DB
    C# 文件打印
    面试题 java集合
    《深入理解Java虚拟机》(六)堆内存使用分析,垃圾收集器 GC 日志解读
    《深入理解Java虚拟机》(五)JVM调优
    《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具
  • 原文地址:https://www.cnblogs.com/houkai/p/3568408.html
Copyright © 2011-2022 走看看