• 二维数组与指针的联系与区别


    例1:
    #include <iostream>
    using namespace std;
    int main()
    {
           int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
           int *ptr = (int *)array;
           int i = 0;
           while (i < 6)
           {
                  cout << "  " << ptr[i];
                  i++;
           }
           
           return 0;
    }
    输出:

    分析:可看出array[0][2]和array[1][0]地址是连续的。

    例2:
    #include <iostream>
    using namespace std;
    int main()
    {
           int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 }};
           int **ptr = (int **)malloc(2 * sizeof(int));
           if (ptr == NULL)
           {
                  cout << "malloc error!" << endl;
                  exit(1);
           }
           for (int i = 0; i < 2; i++)
           {
                  ptr[i] = (int *)malloc(3 * sizeof(int));
                  if (ptr[i] == NULL)
                  {
                         cout << "malloc error!" << endl;
                         exit(1);
                  }
                  for (int j = 0; j < 3; j++)
                  {
                         ptr[i][j] = array[i][j]; // 因为在堆上分配了内存空间
                  }
           }
           for (int i = 0; i < 2; i++)
           {
                  for (int j = 0; j < 3; j++)
                  {
                         cout << "  " << ptr[i][j];
                  }
                  cout << endl;
                  free(ptr[i]);
           }      
           free(ptr);
           return 0;
    }
    输出:


    分析:

    malloc分配的内存空间如上图所示。可看出ptr[0][2]和ptr[1][0]地址不一定是连续的。

    例3
    #include <iostream>
    using namespace std;
    int main()
    {
           int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 }};
           int **ptr = (int**)array; /* array相当于指向一维数组的指针变量;int (*ptr)[3] = array;下面cout << "  " << ptr[i][j]; 就不会报错了。*/
           for (int i = 0; i < 2; i++)
           {
                  for (int j = 0; j < 3; j++)
                  {
                         //cout << "  " << ptr[i][j]; /* 报错! 原因见下面分析 */
                         
                         cout << "  " << *((int*)ptr + 3*i + j);
                  }
                  cout << endl;
                  
           }      
           
           return 0;
    }
    输出:

    分析:重点分析下//cout << "  " << ptr[i][j]这行代码。
     执行 int **ptr = (int**)array; 
    ptr的内存布局如下:

    array的内存布局如下:
     执行 int **ptr = (int**)array;  之后,ptr的值(起始地址)就为array的值,因为32位系统存放地址都是4字节,int也是4字节,所以*(ptr+0)就是取内存里面的数据,刚好值就为array[0][0]。因为ptr是指向指针的指针,所以*(ptr+0)为ptr[0][0]的地址,即&ptr[0][0]值为array[0][0],&ptr[0][1]为array[0][0]+sizeof(int), &ptr[0][2]为array[0][0]+2*sizeof(int) ; *(ptr+1)为ptr[1][0]的地址,即&ptr[1][0]值为array[0][1],&ptr[1][1]为array[1][0]+sizeof(int),&ptr[1][2]为array[1][0]+2*sizeof(int) ;
    为什么 //cout << "  " << ptr[i][j];报错呢?以ptr[0][0]为例,&ptr[0][0]值为array[0][0],这里array[0][0]=1;而地址为1的内存里面的数据是不能访问的,所以报错。

    补充知识:
    如:
    #include <iostream>
    using namespace std;
    int main()
    {
           short int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };   
           short int **ptr = (short int **)array;
           cout << "&array = " << hex << &array << endl;
           cout << "ptr = " << hex << ptr << endl;
           cout << "ptr[0] = " << hex << ptr[0] << endl;
           cout << "ptr[1] = " << hex << ptr[1] << endl;
           cout << "&ptr[0][0] = " << hex << &ptr[0][0] << endl;
           cout << "&ptr[0][1] = " << hex << &ptr[0][1] << endl;
           cout << "&ptr[0][2] = " << hex << &ptr[0][2] << endl;
           cout << "&ptr[1][0] = " << hex << &ptr[1][0] << endl;
           cout << "&ptr[1][1] = " << hex << &ptr[1][1] << endl;
           cout << "&ptr[1][2] = " << hex << &ptr[1][2] << endl;
           
           return 0;
    }
    输出:

    分析:
    short int 是2个字节,而存放地址是4个字节。即array[0][0]占2个字节,ptr[0]也就是*ptr占4个字节。
    因为X86平台是小端序(数据低位存放在低内存地址),所以二维数组内存array内存从低到高前8个字节为:
    注:关于大小端网上资料很多,这里不做讲解。
    ptr[0]取前4个字节,因为是小端序,所以ptr[0]=&ptr[0][0] =0x00020001,
    同理ptr[1]=&ptr[1][0] = 0x00040003;(这里"="理解为等于号)

    例4:
    #include <iostream>
    using namespace std;
    int main()
    {
           int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
           int (*ptr)[3] = array;
           for (int i = 0; i < 2; i++)
           {
                  for (int j = 0; j < 3; j++)
                  {
                         cout << "  " <<  ptr[i][j]; /* 因为ptr是指向一维数组的指针变量,所以完全等价: cout << "  " <<  array[i][j]; */
                         cout << "  " <<  *((int*)ptr + 3 * i + j); // 相当于:cout << "  " << *((int*)array + 3 * i + j);
                  }
                  cout << endl;
           }
                  
           return 0;
    }
    输出:

    例5:
    #include <iostream>
    using namespace std;
    int main()
    {
           int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };  
           int **ptr = (int **)array;
           cout << "array = " << hex << array << endl;
           cout << "array[0] = " << hex << array[0] << endl;
           cout << "ptr = " << hex << ptr << endl;
           cout << "array[0][0] = " << hex << array[0][0] << endl;
           for (int i = 0; i < 2; i++)
           {
                  *(ptr + i) = array[i]; //???
                  cout << "array[0][0] = " << hex << array[0][0] << endl;
                  cout << "array[0][1] = " << hex << array[0][1] << endl;
           }
           return 0;
    }
    输出:

    分析:
    注意:array[0]和ptr[0]意义完全不同。
    array[0]是0行0列地址,即和array的值一样。ptr[0]即*ptr,为地址为ptr值的内存里面存的数据。这程序里刚好为array[0][0]的值,执行*(ptr + i) = array[i];之后,就把ptr值的内存里面存的数据修改为array[i]的值,即array[0][0]也修改为了array[i]的值。

    补充一下:
    如:
    #include <iostream>
    using namespace std;
    int main()
    {
           short array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };       
           short **ptr = (short int **)array;
           cout << "array = " << hex << array << endl;
           cout << "array[0] = " << hex << array[0] << endl;
           cout << "ptr = " << hex << ptr << endl;
           cout << "array[0][0] = " << hex << array[0][0] << endl;
           for (int i = 0; i < 2; i++)
           {
                  *(ptr + i) = array[i]; //???
                  cout << "array[0][0] = " << hex << array[0][0] << endl;
                  cout << "array[0][1] = " << hex << array[0][1] << endl;
                  cout << "array[0][2] = " << hex << array[0][2] << endl;              
                  cout << "array[1][0] = " << hex << array[1][0] << endl;
           }
           return 0;
    }
    输出:

    分析:
    有了上面的分析这就很好理解了。(注意X86平台是小端)
    如果是大端平台,执行 *(ptr + i) = array[i];之后array[0][0]=0x004E,array[0][1]=0xfdbc

    全文总结:最重要一点要明白: 二维数组每个元素内存中是连续存放的,而指向指针的指针变量本质上还是指针变量,即存放地址的变量而已。


  • 相关阅读:
    dubbo服务的运行方式(2)
    朱砂掌健身养生功
    吴清忠养生网
    易筋经十二式
    dubbo入门(1)
    jquery ajax error函数和及其参数详细说明
    com.rabbitmq.client.ShutdownSignalException
    centos 安装rabbitMQ
    SpringMVC @RequestBody接收Json对象字符串
    跨域
  • 原文地址:https://www.cnblogs.com/a3192048/p/12241332.html
Copyright © 2020-2023  润新知