• c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配


    一 数组的结构:顺序存储,看谭浩强中的图,牢记

    1、数组名指代一种数据结构:数组
      现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的char型数组,所以sizeof(str)的结果为这个数据结构占据的内存大小:10字节。
      再看:

    1. int intArray[10];
    2. cout << sizeof(intArray) ;

      第2行的输出结果为40(整型数组占据的内存空间大小)。

      如果C/C++程序可以这样写:

    1. int[10] intArray;
    2. cout << sizeof(intArray) ;

      我们就都明白了,intArray定义为int[10]这种数据结构的一个实例,可惜啊,C/C++目前并不支持这种定义方式。

      2、数组名可作为指针常量

      根据结论2,数组名可以转换为指向其指代实体的指针,所以程序1中的第5行数组名直接赋值给指针,程序2第7行直接将数组名作为指针形参都可成立。
      下面的程序成立吗?

    1. int intArray[10];
    2. intArray++;

      读者可以编译之,发现编译出错。原因在于,虽然数组名可以转换为指向其指代实体的指针,但是它只能被看作一个指针常量,不能被修改。 

      而指针,不管是指向结构体、数组还是基本数据类型的指针,都不包含原始数据结构的内涵,在WIN32平台下,sizeof操作的结果都是4。
    顺便纠正一下许多程序员的另一个误解。许多程序员以为sizeof是一个函数,而实际上,它是一个操作符,不过其使用方式看起来的确太像一个函数了。语句sizeof(int)就可以说明sizeof的确不是一个函数,因为函数接纳形参(一个变量),世界上没有一个C/C++函数接纳一个数据类型(如int)为"形参"。

      3、数据名可能失去其数据结构内涵 

      到这里似乎数组名魔幻问题已经宣告圆满解决,但是平静的湖面上却再次掀起波浪。请看下面一段程序:

    1. #include 
    2. void arrayTest(char str[])
    3. {
    4.  cout << sizeof(str) << endl;
    5. }
    6. int main(int argc, char* argv[])
    7. {
    8.  char str1[10] = "I Love U";
    9.  arrayTest(str1); 
    10.  return 0;
    11. }

      程序的输出结果为4。不可能吧?

      一个可怕的数字,前面已经提到其为指针的长度!

      结论1指出,数据名内涵为数组这种数据结构,在arrayTest函数体内,str是数组名,那为什么sizeof的结果却是指针的长度?这是因为:

      (1)数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;

      (2)很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

      所以,数据名作为函数形参时,其全面沦落为一个普通指针!它的贵族身份被剥夺,成了一个地地道道的只拥有4个字节的平民。

      以上就是结论4。 

    以上转载自:http://blog.chinaunix.net/uid-21765995-id-1815661.html

    二 二维数组

    1 指针数组:元素都是指针的数组,本质是数组  *p[m][n]

    例子:

    int i,j;
    int x[2][3]={{1,2,3},{4,5,6}};
    int *p[2]={x[0],x[1]};//声明一个含有2个元素的一维int指针数组p
    
    for(i=0;i<2;i++)
        {
            for(j=0;j<3;j++)
            {
                cout<<*(p[i]+j)<<endl;
            }
        }

    输出语句为cout<<p[i][j]<<endl;也是可以的。

    int i,j;
    int x[2][3]={{1,2,3},{4,5,6}};
    int *p=x[0]; //x[0]不等价于x,经过程序已经验证。重要x与x[0]的区别,x是二级指针,x[0]一级指针
    for(;p<x[0]+6;p++) { printf("%d ",*p); }

    对比2中的例子,此时p加1是指向下一个元素,2中的例子p加1指向下一行元素的首地址。

    2 数组指针:指向数组的指针 本质是数组 (*P)[m],指向还有m个元素的一维数组,p的增量以数组为单位

    int i,j;
    int x[2][3]={{1,2,3},{4,5,6}};
    int (*p)[3]=x;//声明一个指向具有3个元素的int型数组的指针p
                  //圆括号不可省略
    
    for(i=0;i<2;i++)
        {
            for(j=0;j<3;j++)
            {
                cout<<p[i][j]<<endl;
    
                //或者cout<<*(*(p+i)+j)<<endl;
            }
        }

    以上两种形式都紧扣数组在内存中存储的结构。指针数组比较好理解。数组指针没有理解呀,记住。。。。。。吼!!!

    总的来说:二维数组中x代表行地址,x[0]代表元素地址。把握这个原则。

    *p[2]={x[0],x[1]};//*(p[0]+i)  return p;
    
    *p=x[0];//*(p+i)    return p;
    
    (*p)[3]=x;//*(*(p+i)+j)    return p[0];

    还是有点乱。。不断修改中。

    三 数组的传参问题

    经测试:

    int a[10];
    function(int *a) 传参形式为 function(a)
    funcition(int a[]) 传参形式为function(a)
    
    int a[10][11]
    function(int a[][11])传参形式为function(a)
    function(int **a)传参形式为function(a)    //二维指针的经测试打印错误

      二维数组的传参问题:

    转载自:http://blog.csdn.net/liuzhanchen1987/article/details/7712640

    第一种方式是直接传递二维数组,但是必须标明第二维的值,因为如果只是传递a[][],编译器无法分配这样的数组,所以要这样传int a[][3]

    第二种方法是传递指针数组方式,即int (*a)[3]
    第三种是传递指针方法。

    具体实施见代码:

    //二维数组传参问题示例  
    #include<iostream>  
    using namespace std;  
    //方法1:传递数组,注意第二维必须标明  
    void fun1(int arr[][3],int iRows)  
    {  
        for(int i=0;i<iRows;i++)  
        {  
            for(int j=0;j<3;j++)  
            {  
                cout<<arr[i][j]<<" ";  
            }  
            cout<<endl;  
        }  
        cout<<endl;  
    }  
    //方法二:一重指针  
    void fun2(int (*arr)[3],int iRows)  
    {  
          
        for(int i=0;i<iRows;i++)  
        {  
            for(int j=0;j<3;j++)  
            {  
                cout<<arr[i][j]<<" ";  
            }  
            cout<<endl;  
        }  
        cout<<endl;  
    }  
    //方法三:指针传递,不管是几维数组都把他看成是指针,  
    void fun3(int*arr,int iRows,int iCols)  
    {  
        for(int i=0;i<iRows;i++)  
        {  
            for(int j=0;j<3;j++)  
            {  
                cout<<*(arr+i*iRows+j)<<" ";  
            }  
            cout<<endl;  
        }  
        cout<<endl;  
    }  
    int main()  
    {  
        int a[2][3]={{1,2,3},{4,5,6}};  
        fun1(a,2);  
        cout<<endl;  
        fun2(a,2);  
        cout<<endl;  
        //此处必须进行强制类型转换,因为a是二维数组,而需要传入的是指针  
        //所以必须强制转换成指针,如果a是一维数组则不必进行强制类型转换  
        //为什么一维数组不用强制转换而二维数组必须转换,此问题还没解决,期待大牛!  
        fun3((int*)a,2,3);  
        cout<<endl;  
    }  

    方法四:

    int sum(int *a)
    {
        int i,j;
        int he=0;
        for(i=0;i<3;i++)
        {
            for(j=0;j<2;j++)
            {cout<< *(a+j+i)<<"**"<<endl;
            cout<<i+j<<endl;}
        }
       
        return he;
    }
    
    int main()
    {
        int i,j;
        
        int a[2][3];
        int b[3]={1,2,3};
    
        for(i=0;i<3;i++)
        {
            for(j=0;j<2;j++)
                a[j][i]=i+j;
        }
           
        cout<<sum(a[0])<<endl;
        return 0;
    }

     四 二维数组动态分配内存

    方式一:

    int (*p)[5];
    p=new int[3][5];
    或者
    int (*p)[5]=new int[3][5];

    方式二:

    int **p;
    int i;
    p=new int*[3];
    for(i=0;i<3;i++)
      p[i]=new int[5];

     

  • 相关阅读:
    opencv-活体检测
    人脸识别
    Opencv-python基本操作
    白话深度学习与Tensorflow(二)
    Linux系统入门(一)-未完成
    编程题29 题目:求对角线元素之和
    编程题28 题目 排序
    编程题27 题目:求100之内的素数
    编程题 18兵乓球比赛
    编程题21 求阶数总和
  • 原文地址:https://www.cnblogs.com/dongzhuangdian/p/5059884.html
Copyright © 2020-2023  润新知