精华内容
下载资源
问答
  • 数组形参

    2014-05-05 16:42:54
    如果一个函数一维数组为参数,我们可以这样声明这个函数 void func(int* a) ; void func(int a[]) ; void func(int a[3]) ; 实际上,这三种形式是等价使用数组做参数,编译器会自动将数组名转换为指向...

    如何使用数组参数

    如果一个函数以一维数组为参数,我们可以这样声明这个函数

    void func(int* a) ;
    
    void func(int a[]) ;
    
    void func(int a[3]) ;

    实际上,这三种形式是等价的,在使用数组做参数时,编译器会自动将数组名转换为指向数组第一个元素的指针,为什么呢?这要从参数的传递方式说起,参数有三种传递方式,按值传递,按指针传递,按引用传递,分别如下

    void Test(int a) ;
    
    void Test(int* a) ;
    
    void Test(int& a) ;

    第一种方式传递的是a的一个副本

    第二种方式传递的是指向a的指针的一个副本

    第三种方式传递的是指向a的引用的一个副本

    既然都是副本,那么就存在拷贝到过程,但是,数组是不能直接拷贝的,也就是不能像下面这样

    int a[3] = {1, 2, 3} ;
    
    int b[](a) ;    // error
    
    int b[3] ;
    
    b = a ;            // error
    
    
    不能用一个数组初始化另一个数组,也不能将一个数组直接赋值给另外一个数组,如果想复制数组,唯一的办法就是逐个元素复制。
    
    int a[3] = {1, 2, 3} ;
    
    int b[3] ;
    
    for (int i = 0; i < 3; ++i)
    
    {
    
        b[i] = a[i] ;
    
    }
    

    既然数组不能拷贝,那么参数该如何传递呢?于是编译器就将数组名转换成了指向第一个元素的指针,指针是可以拷贝的。但是这也引发了另外一个问题。我们无法只通过数组名得知数组元素的个数。看下面的代码

    void Test(int a[3])
    
    {
    
        for (int i = 0; i < 5; ++i)
    
        {
    
            cout << a[i] << endl ;
    
        }
    
    }

    明明只传递了三个元素的数组,为什么输出5个元素?前面已经说了,数组被转换成了指向第一个元素的指针,所以上面的代码和下面的相同

    void Test(int* a) //我只知道a是个指针,跟本不知道a指向多少个元素
    
    {
    
        for (int i = 0; i < 5; ++i)
    
        {
    
            cout << a[i] << endl ;
    
        }
    
    }

    编译器根本不知奥数组a有多少个元素,它甚至不知道a是数组!如何解决呢,一种办法是再加一个参数,指定元素个数

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

    另外一种办法是传递数组的引用,这才是本文的重点,唉,前面这么多废话:(

    void Test(int (&a)[3])
    
    {
    
        for (int i = 0; i < 3; ++i)
    
        {
    
            cout << a[i] << endl ;
    
        }
    
    }

    这样写数组a就不会被转换为指针了,而且有了元素个数的信息,调用的时候,也必须传递一个含有3个元素的数组

    int a[3] = {1, 2, 3} ;
    
    Test(a) ;    // ok
    
    int b[1] = {1} ;
    
    Test(b) ;    // error, can not convert parameter a from int[1] to int(&)[3]
    
    
    


    定义数组的引用:
            类型名 (&变量明)[N];
            
    实例:
            int int_array[10];
            int (&int_ref)[10] = int_array;
            这样就得到了一个数组的应用

            在函数的声明中用数组的引用定义,就不怕数组退化了。如下
            for_each( int (&int_ref)[10] )
            {
                     for( int i=0; i<10; ++i )
                             std::cout << int_ref[i] << std::endl;
             }

             int main( int argc, char* argv[] )
             {
                     int int_array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
             
                     for_each( int_array );
                     return 0;
              }

              在上面的代码中,如果你传入不是10个元素的数组,是编译通不过的。代码的安全性提高了。 

    作者:zdd
    出处:http://www.cnblogs.com/graphics/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
    展开全文
  • 为编写将二维数组作为参数的函数,必须牢记,数组名被视为地址,因此相应的形参是一个指针,比较难处理是如何正确声明指针。被调用函数中对形参数组定义可以可以指定所有维数大小,也可以省略第一维的大小...

    为编写将二维数组作为参数的函数,必须牢记,数组名被视为地址,因此相应的形参是一个指针,比较难处理的是如何正确声明指针。

    在被调用函数中对形参数组定义时可以可以指定所有维数的大小,也可以省略第一维的大小说明。如:

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

    二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:
    void Func(int array[][]);

    将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。编译器是这样处理数组的:对于数组 int p[m][n];

    如果要取p[i][j]的值(i>=0 && i< m && 0<=j && j < n),编译器是这样寻址的,它的地址为: p + i*n + j;

    从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。

    下面我们提供三种方式对二维数组进行传参:

    一、在声明的时候,给入第二维维数大小

    void printArray(int (*arr)[9], int w, int h) {
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                cout << arr[i][j] << " ";
            }
            cout << endl;
        }
    }

    二、在声明的时候,用一维指针去指向二维数组, 模拟编译器寻址

    由一知道,如果要把这个数组进行封装,是不适用的,因为你直接函数中

    写死了二维数组的第二维维数大小
    void printArray2(int * arr, int w, int h) {
    
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                cout << arr[i*w+j] << " ";
            }
            cout << endl;
        }
    
    }

    三、建立一个指针数组,进行指向原二维数组,同时在函数中传入二维指针

    void printArray3(int ** arr, int w, int h) {
    
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                cout << arr[i][j] << " ";
            }
            cout << endl;
        }
    
    }

    测试:

    int main(void) {
    
        int arr[][9] = { { 0,0,0,0,0,0,0,0,0 },
                        { 0,1,1,0,1,1,1,1,0 },
                        { 0,1,1,1,1,0,0,1,0 },
                        { 0,1,1,0,1,0,0,0,0 },
                        { 0,0,0,0,1,1,1,0,0 },
                        { 0,0,0,0,1,1,1,0,0 },
                        { 0,0,0,0,0,0,0,0,0 } };
    
        cout << "=============== method 1 ===============" << endl;
        printArray(arr, 9 ,7);
    
        cout << "=============== method 2 ===============" << endl;
        printArray2(*arr, 9, 7);
    
        cout << "=============== method 3 ===============" << endl; 
        int *p[7]; // define array of pointers (指针数组)
        for (int i = 0; i < 7; i++)
            p[i] = arr[i];
        printArray3(p, 9, 7);
    
        system("pause");
        return 0;
    }
    展开全文
  • 如果我们要编写一个函数对这个数组进行处理,我们应该怎样声明函数的形参,又怎样调用函数引入二维数组这个参数呢? 首先我们来看对一维数组是怎么做的 void main() { int vec[n]; fun1(vec); } 对...

    问题:已有二维数组a[n][m] (m,n为常量整数)

    int a[n][m];

    如果我们要编写一个函数对这个数组进行处理,我们应该怎样声明函数的形参,又怎样在调用函数时引入二维数组这个参数呢?

    • 首先我们来看对一维数组是怎么做的

    void main()
    {
        int vec[n];
        fun1(vec);    
    }

    对函数传参时,直接把一维数组的名字作为参数传入。

    在定义函数的形参时有两种方式

    void fun1(int *vec);
    
    void fun1(int vec[]);
    

    因为这里的vec同时也是一个指向整形的指针,指向的是数组第一位的元素,所以以上两种形参都是符合要求的。

    在fun1函数的实现里面,可以通过*(vec+i)或者vec[i]来访问数组元素。

    • 那么二维数组是跟上面的方法一样吗

    如果是按一维数组的方式,会写成这样

    void fun2(int **a)
    {
        a[i][j];
    }
    void main()
    {
        int a[n][m];
        fun2(a);
    }
    

    这是错误的写法。原来我是错误的把二维数组的名字a理解成指针的指针,而实际上这里的a是一个指向整形数组的指针

    int (*p)[m];

    比如这个p就是一个指向包含m个整形元素的数组的指针,p=a的操作是合法的。

    所以fun2的原型可以是以下形式(假设m=10)

    void fun2(int (*mat)[10]); //假设m=10
    void fun2(int mat[][10]);

    这样我们就可以在函数原型中访问二维数组的元素mat[i][j]
    这里我们需要注意的是在定义时多维数组的第2个及以后的下标不能为空,为什么是这样设定呢,拿二维数组举例,二维数组的元素在内存空间的地址是连续的,从mat[0][0]开始,一直到mat[0][m-1],接着是mat[1][0]到mat[1][n-1],也就是说“每一行”的数据是接在上一“行”数据的后面存放的所以mat[i][j]相对于mat[0][0]的位置是i*(m-1)+j,编译器就是通过这样的方式来从一维的存储地址中找到二维数组的元素,所以第二维的长度m的值是必须的,而第一维的长度n的值是可以省略的。

    • 如果定义形参时不知道数组的大小呢

    对于一维数组来说,因为在定义形参时是不用指明数组大小的,自然没有这个问题,但是二维数组作为形参时是至少要写明第二维及以后的维度的长度,而很多时候数组的大小是不确定的,这时该怎么办呢。

    这时我们可以想,如果可以像一维数组一样可以通过第一个元素的地址加上偏移量来访问数组元素就好了,实际上这是可行的。

    上面提到二维数组名字a是“一个指向包含m个整形元素的数组的指针”,同一维数组名字vec指针指向的是数组的第一个元素相似,二维数组名字a指向的是二维数组中第一个“包含m个整形元素的数组”,即以0为一维坐标的这段数据的这个数组a[0],对a这个一维数组再取地址&a,就可以得到a[0][0]的地址,即整个二维数组在存储空间中的第一个数的地址,通过这个地址,再结合上面提到的求二维数组的地址偏移量的方法就可以实现通过首地址加地址偏移量的方法来访问数组的内容。所以我们可以用下面这种方式实现

    void fun2(int *head,n,m)
    {
        *(head+i*(m-1)+j) //访问mat[i][j]的值
    }
    
    void main()
    {
        int n,m;
        ...     //给n和m赋值
        int mat[n][m];
        fun2(&mat,n,m);
    }

    以上理论参考自《c和指针》p159

    总结:二维数组的不同主要还是因为二维数组的名字和一维数组的名字的含义不同,还有二维数组的存储方式对于语法的影响,这些都跟编译器的设定有关,更高维的数组又是什么样的设计还没了解,记得以前见过一个题提到java中二维数组必须有第一维的长度,而c中必须有第二维的长度,是因为java的二维数组是另外一种存储方式还是因为java的编译器是另外的寻址规则,这些还可以进行更加深入的探究

     

    展开全文
  • 数组作为函数的参数

    2018-09-18 16:23:10
    如果函数的实参是数组名,则...实际上,声明形参数组并不意味着真正建立一个包含若干元素的数组,调用函数也不对它分配存储单元,只是用array[]这样的形式表示array是一维数组名,以接收实参传来的地址。因此ar...

    如果函数的实参是数组名,则形参肯定也为数组名或者指针变量。且实参数组和形参数组类型必须一致。函数实参是数组名,即是把数组首元素的地址传递给形参。数组名作函数实参时,改变形参数组元素的值将同时改变实参数组元素的值。

    实际上,声明形参数组并不意味着真正建立一个包含若干元素的数组,在调用函数时也不对它分配存储单元,只是用array[]这样的形式表示array是一维数组名,以接收实参传来的地址。因此array[]中方括号内的数值并无实际作用,编译系统对一维数组方括号内的内容不予处理。形参一维数组的声明中可以写元素个数,也可以不写。

    void BubbleSort(int num[])//升序排列
    {
    	for(int i = 0; i < N - 1;i++)
    	{
    		for(int j = i + 1; j < N ;j++)
    		{
    			if(num[i] > num[j])
    			{
    				int temp = num[i];
    				num[i] = num[j];
    				num[j] = temp;
     
     
    			}
    		}
    	}
    }
    

    上面的写法不能得知实参数组含有的元素大小,若要传递数组的大小,可以在后面再添加个形参变量,表示数组的个数。

    void BubbleSort(int num[],int n)

    下面这个三个函数声明效果是一样的

    void fun1(char *a,int length);  //数组名
    void fun2(char a[],int length);  //数组名
    void fun3(char a[10],int length);   //数据名
    

    fun3参数a[10]中的10有跟没有都一样的,编译器都会忽略掉

    多维数组名作函数形参
    如果用二维数组名作为实参和形参,在对形参数组声明时,必须指定第二维(即列)的大小,且应与实参的第二维的大小相同。第一维的大小可以指定,也可以不指定。如:
    int array[3][10];  //形参数组的两个维都指定    

    int array[][10];  //第一维大小省略  二者都合法而且等价,但是不能把第二维的大小省略。

    下面的形参数组写法不合法:

    int array[][];  //不能确定数组的每一行有多少列元素 int array[3][];  //不指定列数就无法确定数组的结构

    在第二维大小相同的前提下,形参数组的第一维可以与实参数组不同。例如,实参数组定义为:int score[5][10];

    而形参数组可以声明为:int array[3][10];   int array[8][10];  //列数与实参数组相同,行数不同 

    形参声明为int array[3][10];   int array[8][10];    int array[ ][10];这三种是等价的
    形参二维数组与实参二维数组必须由相同类型和大小的一维数组组成的,实参数组名score代表其首元素(即第一行)的起始地址,系统不检查第一维的大小。

    展开全文
  • 数组名做函数参数

    2019-12-21 20:42:01
    给大家写一个数组名作为函数参数吧 此特别说明: 数组名作为函数参数,需要分别背调函数与主调函数中说明数组类型,并且要求实参与形参...一维数组函数参数函数声明的语法格式: void disp(int a[10],i...
  • C++中如何将数组作为函数参数

    千次阅读 2019-07-21 21:03:43
    声明形参数组并不意味着真正建立一个包含若干元素数组,调用函数时也不对它分配存储单元,只是用array[ ]这样形式表示array是一维数组的名字,用来接收实参传来地址。因此,array【 】中数值并无实际作用...
  • 对于一维数组而言可以直接传递首地址 而对于二维数组必须传递时声明是二维数组指针,并且调用也要经过一些运算 首先是定义形参函数名(int *arg) 向这个形参传递实参: 函数名(&data[0][0]...
  • 高质量C++编程指南中指出当数组作为函数的参数进行传递,该数组自动退化为同类型的指针,这句话针对一维数组是正确的(目前个人认为是正确的),但是对于多维数组,这显然不完全正确。C语言之所以把数组形参...
  • 数组参数

    2012-05-15 10:42:48
    高质量C++编程指南中指出当数组作为函数的参数进行传递,该数组自动退化为同类型的指针,这句话针对一维数组是正确的(目前个人认为是正确的),但是对于多维数组,这显然不完全正确。C语言之所以把数组形参当作指针...
  • 形参是指声明或定义函数时的参数,而实参是调用函数时主调函数传递过来实际值。 一、一维数组参数 1、能否向函数传递一个数组?看例子: void fun(char a[10]) {  char c = a[3]; } intmain() {
  • 1.在数组函数形参时,A[][3]表示一个第二 的角标个数是3的一数组,传入实参B [i][j]时,j=3,而i能满足函数体里的语句 的需要即可。 2.A[i][j]做函数形参时,实参B[m][n]的要求 是n=j且m>=i。 3.操作系统...
  • 如果在声明数组时给每数组元素指定初始值,在数组初始化过程中就会调用与形参类型相匹配构造函数,例如: Location a[2]={ Location(1,2), Location(3,4)}; 实例: Point.h: #ifndef _POINT_H #defi
  • 参数相信大家都清楚,它是分为实参和形参,实参话就是主函数调用函数时,实际传过去值,而形参声明和定义函数时的参数。 一维数组参数 先看一个例子 void fun(char a[10]) { char c = a[3];...
  • C语言假期学习笔记——6 数组 主要学习了一位数组和二...第一维长度某些时刻可以省略(当形参声明为二维数组时),第二维长度永远不可以省略 存储元素总量=第一维长度*第二维长度 向函数传递数组 先对数组...
  • JavaScript入门

    2020-05-19 18:35:52
    二维数组可以认为是特殊的的一维数组,即一维数组中的每个元素又是一个一维数组 语法: 6.函数 6.1自定义函数 语法: 注意: ·定哟函数时不需要指定参数的类型 ·实参个数和形参个数可以不同,未给形参传入实参的...
  •  6.1.2怎样引用一维数组元素  6.1.3一维数组的初始化  6.1.4一维数组程序举例  6.2.怎样定义和引用二维数组  6.2.1怎样定义二维数组  6.2.2怎样引用二维数组元素  6.2.3二维数组初始化  6.2.4二维数组...
  • 6.1怎样定义和引用一维数组143 6.1.1怎样定义一维数组144 6.1.2怎样引用一维数组元素145 6.1.3一维数组的初始化146 6.1.4一维数组程序举例147 6.2怎样定义和引用二维数组149 6.2.1怎样定义二维数组150 6.2.2怎样引用...
  • 【零基础搞定C语言——7】

    千次阅读 多人点赞 2021-04-24 17:31:46
    文章目录1.除了形参使用数组或者指针,通过全局变量也能做到把...二维数组在内存中是连续存储8.冒泡排序9.数组名是什么? 1.除了形参使用数组或者指针,通过全局变量也能做到把函数处理结果二个数据返回给主
  • C程序设计(第四版).谭浩强.扫描版

    热门讨论 2011-05-31 10:02:13
    6.1怎样定义和引用一维数组142 6.1.1怎样定义一维数组143 6.1.2怎样引用一维数组元素144 6.1.3一维数组的初始化145 6.1.4一维数组程序举例146 6.2怎样定义和引用二维数组148 6.2.1怎样定义二维数组149 6.2.2怎样引用...
  • C程序设计(第四版)【谭浩强】

    热门讨论 2011-05-25 15:55:43
    6.1.2怎样引用一维数组元素144 6.1.3一维数组的初始化145 6.1.4一维数组程序举例146 6.2怎样定义和引用二维数组148 6.2.1怎样定义二维数组149 6.2.2怎样引用二维数组元素150 6.2.3二维数组初始化151 6.2.4二维...
  • 7.1 一维数组的定义和一维数组元素引用 45 7.1.1 一维数组的定义 45 7.1.2 一维数组元素引用 46 7.1.3 一维数组的初始化 46 7.1.4 一维数组的定义和数组元素引用举例 47 7.2 函数之间对一维数组和数组元素...
  • c++(三)

    2019-09-30 17:07:15
    函数调用之前必须进行声明或者定义,函数的声明:返回值类型 函数名(参数类型 参数名称.......);其中参数名称可以省略; 函数的形参是实参的一个拷贝,形参改变实参不会改变,除非参数是数组,引用; 数组作为参数传递...
  • 6.1 怎样定义和引用一维数组 6.1.1 怎样定义一维数组 6.1.2 怎样引用一维数组元素 6.1.3 一维数组的初始化 6.1.4 一维数组程序举例 6.2 怎样定义和引用二维数组 6.2.1 怎样定义二维数组 6.2.2 怎样引用二维数组...
  • 例如定义个包含N个指向返回指向字符的指针的函数的指针的数组?  1.22 如何声明返回指向同类型函数的指针的函数?我设计个状态机,用函数表示每种状态,每个函数都会返回个指向下个状态的函数的指针。可...

空空如也

空空如也

1 2 3 4
收藏数 61
精华内容 24
关键字:

在声明函数的一维数组形参时