精华内容
下载资源
问答
  • 一维数组作为函数形参
    万次阅读 多人点赞
    2012-04-04 21:14:19

    如何将一维数组作为函数形参来使用

    请看下面的程序:
            #include <stdio.h>
            void func1(int arr[])
            {
                    printf("%d\n",sizeof(arr));
                    arr=arr+1;
                    printf("%d\n",*arr);

    }
            void func2(int *arr)
            {
                    printf("%d\n",sizeof(arr));
                    arr=arr+1;
                    printf("%d\n",*arr);
            }

    int main()
            {
                    int a[10]={1,2,3,4,5};
                    int *b=a;
                    printf("%d\n",sizeof(a));
                    func1(a);
                    func2(a);

            printf("%d\n",sizeof(b));
                    func1(b);
                    func2(b);

                    //a=a+1;
                    printf("%d\n",*a);
                    b=b+1;
                    printf("%d\n",*a);
                    return 0;
            }

    为了说明问题,我写了一个简单的测试程序,在主函数中定义了一个a数组,并定义了一个b指针指向该数组的首地址。显然a=a+1是不能通过编译的,因为作为数组而言,a是地址常量,一旦定义是不允许指向其他地址的。

    那么作为b,其仅仅是一个指针变量,里面存放的是a数组的首地址,故可以执行b=b+1,这样使得b指向a+1,也就是a数组中的a[1]。

    下面问题就来了,我们该如何将一个数组作为形参传递给函数,也就是说若有一个实参数组,想在函数中改变此数组中的元素的值,我们该如何处理?

    数组作为形参,和接受它的实参有以下的关系:

    1. 形参和实参都是数组名。
            2. 实参用数组,形参用指针变量.
            3. 实参、形参都用指针变量。
            4. 实参为指针变量,形参为数组名。

    在上述的例子中我们来进一步的讲解。

    首先来看结果:

    40//sizeof(a)
            4//func1(a)
            2//arr=arr+1
            4//func2(a)
            2//arr=arr+1
            4//sizeof(b)
            4//func1(b)
            2// arr=arr+1
            4//func2(b)
            2// arr=arr+1
            1// a
            1//b=b+1;

    在C语言中,数组名是当作指针来处理的。更确切的说,数组名就是指向数组首元素地址的指针,数组索引就是距数组首元素地址的偏移量。理解这一点很重要,很多数组应用的问题就是有此而起的。这也就是为什么C语言中的数组是从0开始计数,因为这样它的索引就比较好对应到偏移量上。在C语言中,编译过程中遇到有数组名的表达式,都会把数组名替换成指针来处理;编译器甚至无法区分a[4]和4[a]的区别。

    我们在题中定义了

    int a[10];
            int *b;

    这两者并不等价,第一句话声明了数组a,并定义了这个数组,它有10个int型元素,sizeof(a)将得到整个数组所占的内存大小,是40;第二句话只是声明并定义了一个int型的指针,sizeof(b)将得到这个指针所占的内存大小,是4。所以说,虽然数组名在表达式中一般会当作指针来处理,但是数组名和指针还是有差距的,最起码有a==&a[0]但是sizeof(a)!=sizeof(a[0])。

    并且在ANSI C标准中,也明文规定:在函数参数的声明中,数组名可以当作指向该数组第一个元素的指针。所以,下面的几种书写形式是等效的:

    void func1(int arr[]){}
            void func2(int *arr){}

    对于第一种还可以写成void func1(int arr[100]){},在形参中其实不需要指定数组的大小,因为其实在这几个函数在函数调用时传入的只是一个该数组的指针,想要确定几行几列的话还需要另外定义参数进行传入.如果在使用该指针的过程中不清楚原数组的范围,指针很容易就越界,内存也就溢出了。

    当用数组名作函数参数时,形参数组就可以从实参数组那里得到起始地址后,形参数组就和实参数组共占同一段内存单元,从而在调用函数期间,如果改变了形参数组的值,也就该变了实参数组的值。

    最后要补充一点,也就是上次我们学员问我的一个问题,作为形参int arr[]和int *arr有什么区别。在本质上,我们看通过程序,貌似真的没有区别,虽然arr[]是作为数组传递进去,但是我们也可以修改arr的指向,而作为实参的数组的a却不能使其加一。我们都知道函数之间的参数传递有:复制传递方式、地址传递方式、全局变量。

    那么姑且就将void func1(int arr[])最为函数按复制传递的方式,而void func2(int *arr)作为其地址传递的方式。而复制传递方式与数组的指针传递方式是完全相同,只是形参的说明形式不同而已。调用函数将实参数组传递给被调用函数形参,形参接收是实参的地址。不论哪种方式,被调用函数里对形参数组的操作都会影响调用函数里的实参数组。

    更多相关内容
  • 作者:王姗姗,华清远见嵌入式学院讲师。  请看下面的程序:  #include  void func1(int arr[])  {  printf("%d\n",sizeof(arr));  arr=arr+1;  printf("%d\n",*arr);... int a[10]={1,2,3,
  • 作者:王姗姗,华清远见嵌入式学院讲师。  请看下面的程序:  #include  void func1(int arr[])  {  printf("%d\n",sizeof(arr));  arr=arr+1;  printf("%d\n",*arr);... int a[10]={1,2,3,
  • 一维数组作为函数形参

    千次阅读 2018-04-25 14:53:53
    个例子引发的思考   运行以下代码,请问输出是什么?例子来源于《剑指Offer》,我对书上例子做了修改,让其可以运行。 #include using namespace std; int GetSize(int data[]) { return sizeof(data); ...

    转载:https://blog.csdn.net/oNever_say_love/article/details/49422517

    一、一个例子引发的思考

      运行以下代码,请问输出是什么?例子来源于《剑指Offer》,我对书上例子做了修改,让其可以运行。

    #include<iostream>
    using namespace std;
    
    int GetSize(int data[]) {
        return sizeof(data);
    }
    int main() {
        int data1[] = {1,2,3,4,5};
        int size1 = sizeof(data1);
    
        int *data2 = data1;
        int size2 = sizeof(data2);
    
        int size3 = GetSize(data1);
    
        cout<<size1<<" "<<size2<<" "<<size3<<endl;
        return 0;
    }
    
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果如下:
    这里写图片描述
      data1是一个数组,sizeof(data1)是求数组的大小。这个数组包含5个整数,每个整数占4个字节,因为总共是20个字节。data2声明为指针,尽管它指向了数组data1,对认真指针求sizeof,得到的结果都是4。在C/C++中,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。因此尽管函数GetSize的参数data被声明为数组,但它会退化为指针,size3的结果仍然是4.

    二、数组的两个特殊性质

    (1)不允许拷贝和赋值

      不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

    int a[] = {0,1,2};    // 含有三个整数的数组
    int s2 = a;           // 错误:不允许使用一个数组初始化另一个数组
    a2 = a;               // 错误:不能把一个数组直接赋值给另一个数组
       
    • 1
    • 2
    • 3

    (2)使用数组是通常将其转化成指针

      在C++语言中,指针和数组有非常紧密的联系。使用数组的时候编译器一般会把它转换成指针。

      通常情况下,使用取地址符来获取指向某个对象的指针,取地址符也可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能的搭配指向该元素的指针:

    string nums[] = {"one", "two", "three"};  // 数组元素是string对象
    string *p = &nums[0];                     // p指向nums的第一个元素
       
    • 1
    • 2

      然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:

    string *p2 = nums;                        // 等价于p2 = &nums[0]
       
    • 1

      在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。

    三、数组形参

      数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
      尽管不能以值传递的方式传毒数组,但是我们可以把形参写成类似数组的形式:

    //尽管形式不同,但这三个print函数是等价的
    //每个函数都有一个const int*类型的形参
    void print(const int*);
    void print(const int[]);
    //这里的维度表示我们期望数组含有多少元素,实际不一定
    void print(const int[10]); 
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

      尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形式都是const int*类型的。当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:

    int i=0,j[2] = {0,1};
    print(&i);               //正确:&i的类型是int*
    print(j);                 //正确:j转船成int* 并指向j[0]
       
    • 1
    • 2
    • 3

      如果我们传给print函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。

      和其他使用数组的代码一样,以数组作为形参的函数也必须确保使用数组时不会越界。

                                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                    </div>
    
    展开全文
  • c语言中经常需要通过函数传递二维数组,有三种方法可以实现,如下: 方法形参给出第二维的长度。 例如: #include void func(int n, char str[ ][5] ) { int i; for(i = 0; i < n; i++) printf("/nstr...
  • 维数组作为函数形参该如何传递

    千次阅读 2020-05-10 17:49:33
    今天在论坛上有朋友提问:声明函数如下void function(int** pInt),意图是想参数...如果要将个二维数组作为形参,那么函数该怎么声明? 来看《C++ Primer》中给出的方法: 1. 数组名作为形参 [cpp] view plain copy

    今天在论坛上有朋友提问:声明函数如下void function(int** pInt),意图是想参数传递一个二维数组。于是就定义了一个二维数组,比如 int[1][1],然后调用函数。结果如何?当然是失败了,编译器提示:cannot convert parameter 1 from ‘int [1][1]’ to ‘int **’,参数类型不匹配。如果要将一个二维数组作为形参,那么函数该怎么声明?

    来看《C++ Primer》中给出的方法:

    1. 数组名作为形参

    [cpp] view plain copy
     
    void func1(int iArray[][10])  
    {  
      
    }  
      
      
      
    int main()  
    {  
        int array[10][10];  
        func1(array);  
      
    }  
     
    
    

    编译通过,注意形参声明一定要给出第二个维度的大小,要不编译不过。

    2. 一维数组指针作为形参

    
    [cpp] view plain copy
     
    void func2(int (*pArray)[10])  
    {  
      
    }  
      
    void func2_1(int (*pArray)[]) //编译通过,无法调用  
    {  
      
    }  
      
    int main()  
    {  
        int array[10][10];  
        func2(array);  
    }  
    

    编译通过,注意形参声明一定要给出第二个维度的大小,要不编译不过。
    一维数组指针作为形参

    其实二维数组名就是一个指向一维数组的指针,所以这种声明方式OK。必须指定一维数组的长度,如果没有指定的话,函数声明编译通过。但是如果一旦有调用代码,就有编译不通过,因为没有实参类型能匹配int[].

    1. 二维数组引用作为形参
    [cpp] view plain copy
     
    void func3(int (&pArray)[10][10])  
    {  
      
    }  
      
    int main()  
    {  
        int array[10][10];  
        func3(array);  
    }  
    

    必须指定两个维度的长度。

    1. 二维数组指针作为形参
    [cpp] view plain copy
     
    void func4(int (*pArray)[10][10])  
    {  
      
    }  
      
    int main()  
    {  
        int array[10][10];  
        func4(&array);  
      
    }  
    

    必须指定两个维度的长度。 以上方法都可以等价使用,对数组来说,没有值传递。

    还不满足,还有其他的声明方式吗?回到本文开始提到的问题:可以用双重指针int**作为形参,接受二维数组实参吗?答案是肯定的,但是又局限性。用双重指针作为形参,那么相应的实参也要是一个双重指针。事实上,这个双重指针其实指向一个元素是指针的数组,双重指针的声明方式,很适合传递动态创建的二维数组。怎么动态创建一个二维数组?如下程序:

    [cpp] view plain copy
     
    int main()  
    {  
        int m = 10;  
        int n = 10;  
        int** p = new int[m][n];  
    }  
     
    

    会发现编译不通过,第二个维度长度必须为常量。那么怎么声明一个两个维度都能动态指定的二维数组呢?看下面:

    [cpp] view plain copy
     
    void func5(int** pArray, int m, int n)  
    {  
      
    }  
      
    #include <ctime>  
    int main()  
    {  
        int m = 10;  
        int n = 10;  
      
        int** pArray = new int* [m];  
        pArray[0] = new int[m * n]; // 分配连续内存  
      
        // 用pArray[1][0]无法寻址,还需指定下标寻址方式  
        for(int i = 1; i < m; i++)  
        {  
            pArray[i] = pArray[i-1] + n;  
        }  
      
        func5(pArray, m, n);  
    }  
    

    pArray -> [ ][ ]…[ ][ ] pArray是一个地址,指向一块m个连续int* 类型数据的内存空间
    pArray[0]是一个地址数据,即是一块m*n大小的二维数组的连续内存空间的地址;
    然后对剩下的m-1个地址数据赋值,让其指向二维数组的对应位置。

    展开全文
  • 维数组作为函数形参

    千次阅读 2018-04-25 15:12:13
    转载:... 在用二维数组作为参数传递时容易出现Segmention Error。这是因为不能正确为二维数组中元素寻址的问题,正确的方法如下:[cpp] view plaincopy #include <stdlib.
    转载:https://blog.csdn.net/u014082714/article/details/45071791

    在用二维数组名作为参数传递时容易出现Segmention Error。这是因为不能正确为二维数组中元素寻址的问题,正确的方法如下:

    [cpp]  view plain copy


    1. #include <stdlib.h>    

    2. #include <stdio.h>    

    3.     

    4. #define N   4    

    5. void testArray(int *a, int m, int n)    

    6. {    

    7.     for(int i = 0; i < m; ++i)    

    8.         for(int j = 0; j < n; ++j)    

    9.         {    

    10.             printf(”a[%d][%d] = %d\n”, i, j, *(a+i*n+j));    

    11.         }    

    12. }    

    13.     

    14. int main()    

    15. {    

    16.     int a[2][N] = {{1, 2, 3, 4}, {5, 6, 7, 8}};    

    17.     

    18.     testArray((int *)a, 2, N);    

    19. }    






    1. 将二维数组的两个维度用变量的形式传递过去

    如下所示:

    [cpp]  view plain copy


    1. #include <stdlib.h>  

    2. #include <stdio.h>  

    3.   

    4. #define N   4  

    5. void testArray(int **a, int m, int n)  

    6. {  

    7.     for(int i = 0; i < m; ++i)  

    8.         for(int j = 0; j < n; ++j)  

    9.         {  

    10.             printf(”a[%d][%d] = %d\n”, i, j, ((int)a + i * n +j));  

    11.         }  

    12. }  

    13.   

    14. int main()  

    15. {  

    16.     int a[2][N] = {{1, 2, 3, 4}, {5, 6, 7, 8}};  

    17.   

    18.     testArray((int **)a, 2, N);  

    19. }  


    此时在子函数中不能使用a[i][j]的形式访问数组元素,因为数组元素都是顺序存储,地址连续,在使用a[i][j]访问数组元素时,无法顺序访问到指定的元素,所有我们只能通过计算指定所要访问的元素。

    2、用指向一维数组的指针变量,如下例子所示:

    [cpp]  view plain copy
    1. #include <stdlib.h>    
    2. #include <stdio.h>    
    3.     
    4. #define N   4    
    5. void testArray(int (*a)[4], int m, int n)    
    6. {    
    7.     for(int i = 0; i < m; ++i)    
    8.         for(int j = 0; j < n; ++j)    
    9.         {    
    10.             printf(”a[%d][%d] = %d\n”, i, j, *(*(a+i)+j));  //printf(“a[%d][%d] = %d\n”, i, j, a[i * n +j]);    
    11.         }    
    12. }    
    13.     
    14. int main()    
    15. {    
    16.     int a[2][N] = {{1, 2, 3, 4}, {5, 6, 7, 8}};    
    17.     
    18.     testArray(a, 2, N);    
    19. }    

    int (*a)[N] 表示指向一维数组的指针变量,即a所指向的对象是含有4个整型元素的数组。注意 () 不能少,若定义成:

    int *a[N] 则表示有一个一维数组a[N],该数组中的所有元素都是 (int *)类型的元素。

    在这里,在子函数中访问二维数组中的元素可以用 a[i][j] 或者 *(*(a+i)+j)

    在这种情况下((a+i))[j],a [i n +j]);,((a+i)+j),a[i][j],((int)a + i * n +j)都可以进行访问。


    展开全文
  • 维数组作为函数形参的两种方法

    热门讨论 2012-01-04 20:37:14
    最简单的二维数组求和程序,用函数来实现,代码简单易懂,希望对您有帮助
  • 通过指针变量指向一个一维数组(字符串 char类型) char a[20]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’}; //定义一个数组名为 a 长度为20 的char类型变量 char a[20] = “abcdefg”; //定义一个数组名为 a 长度...
  • 1. 二维数组常用创建方法 静态二维数组 ① 确定行和列 a. 不确定元素 int a[2][2]; b. 部分元素确定 int a[2][3] ={1,2,3,4}; c. 确定元素 int a1[2][2] = {{1,2,}{3,4}};//标准的二维数组初始化方式 //在写明列号...
  • 一维数组进行传参的时,函数参数可以写成数组或指针(因为数组名是地址,故可用指针接收); 其中参数是数组时,数组大小可写也可不写; 参数是指针时要找到对应的指针类型才行; 传递参数是普通数组 arr(3种方式...
  • 一维数组用于函数的参数
  • C++ 二维数组作为函数形参

    千次阅读 2016-12-26 11:42:58
    形参必须指定数组第二位长度,第一维长度指定不指定都可以#include #include #include void shownum(int num[][3]); using namespace std; int main() { int num[3][3]; for(int i=0; i; i++) fo
  • 本文主要针对维数未知二维数组作为函数形参进行传递时的形参类型声明问题,具体声明方法如下代码所示; 注意: 下面这种声明方式是错误的,编译器会提示m, n unclear,这可能是因为编译器顺序编译的原因吧,但只要...
  • C++ 数组作为函数形参

    千次阅读 2019-12-05 15:10:49
    代码行都有注释,就不多说了,有错误欢迎指正~ #include<...// 一维数组方式1 void fun1(int a[], int m) { for(int i=0;i<m;i++) cout<<a[i]<<endl; } // 一维数组方式2 void fun2(in...
  • 维数组作为函数形参的函数声明

    千次阅读 2016-09-03 22:19:13
    如果我们需要编写个处理二维数组函数,那么这个函数原型应该如何声明呢? 首先,我们应该牢记:数组名被视为其地址,因此,相应的形参个指针。例如,假设有如下的代码: [cpp] ...
  • c/c++ 一维数组、二维数组作为函数参数、返回值 一、一维数组作为参数 传入数组 int [] 为了规范,常常需要将数组的size一同传入,这是因为C++/C遇到参数为数组时,不会去一个个拷贝数组内的元素(太过于耗时),...
  • 指向一维、二维数组的指针 例:int vector[10], *vp=vector;//① int vector[3][10], *vp=vector;//② ①合法,它为一个整型数组分配内存,并把vp声明为一个指向整型的指针 ②为何不合法,vp的初始化是有问题的...
  • 一个变量有地址,一个数组也有地址,不同的是数组...一维数组整型类(int) 通过指针变量指向一个一维 int 类型数组元素: int a[5]={0,1,2,3,4}; //定义一个数组名为 a 长度为5 的int类型变量 int *pa; //定义一...
  • 维数组传参(二维数组作为函数参数)

    千次阅读 多人点赞 2021-11-23 20:13:52
    维数组传参,函数形参的设计只能省略第个[ ]的数字; 因为对于二维数组,可以不知道有多少行,但必须知道行多少个元素; #include<iostream> using namespace std; void test(int arr[3][4]) { // ...
  • 当二维数组作为函数形参时,能作为函数实参的是二维数组,数组指针 d.当指针数组作为函数形参时,能作为函数实参的是指针数组,二级指针,级指针的地址 实例验证: #include <stdio.h> #includ...
  • 维数组作为形参

    千次阅读 2021-08-26 10:41:22
    首先需要理解编译器对于二维数组是如何寻址的: ...因此如果想要采用数组下标的形式作为形参,则必须给定n值(该即二维数组一行有多少列),否则无法定位出所寻址行的首地址,则无法进行正常的寻址。
  • 一、一维数组形参退化、 二、二维数组形参退化、 三、数组形参等价关系、
  • 指针数组引发的疑问
  • `param1`为二维数组,在函数`void total_score_of_each_stu(param1, param2, param3,param4)`中该以怎样的形参形式去接收函数调用时实参传递的参数?
  • 形式参数解读什么是形式参数形式参数的作用域...其作用是实现主调函数与被调函数之间的联系,通常将函数所处理的数据,影响函数功能的因素或者函数处理的结果作为形参。 形式参数不是实际存在变量,只有在程序执行过
  • 文章目录指针数组数组首元素和数组的地址、空间大小数组名指针和数组相同点使用上作为函数形参上不同点二维数组数组指针二维数组和数组指针相同点不同点一维数组和数组指针指针数组指针数组和数组指针二级指针总结 ...
  • 一维数组作为函数形参 想在函数内部操作外部数组的元素,需要传递数组名,因为数组名是数组的首地址 一维数组作为函数形参会被优化为指针 二维数组名作为函数形参 二维数组作为函数形参会被优化为数组指针(二...
  • C语言二维数组作为函数参数传递

    万次阅读 多人点赞 2018-06-07 21:43:37
    维数组作为函数的参数,实参可以直接使用二维数组名,在被调用函数中可以定义形参所有维数的大小,也可以省略以为大小的说明。例如: void find(char a[3][10]); void find (char a[ ][10]); 也可以使用数组...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,666
精华内容 11,066
热门标签
关键字:

一维数组作为函数形参