C++指针--指针与数组

1. 一维数组与指针


*  数组指针

      数组的首地址称为数组指针。若定义整型数组a[5],系统为数组分配的地址从1000到1019,则数组a的首地址1000为数组a的数组指针。
      C++规定,数组的首地址可用数组名a表示,因此,数组a的数组指针=a=&a[0]。

* 数组指针变量

      存放数组元素地址的变量称为数组指针变量。如:
      int a[5];
      int *p=&a[0];
      则p为数组指针变量。
      在C++中数组名a可用于表示数组的首地址,所以数组名a可作为数组指针使用。因此:p=a与p=&a[0] 的作用是相同的。
      但数组名a不能用来进行赋值运算、"++"、"- -"等运算。
      当指针变量指向数组首地址后,就可使用该指针变量对数组中任何一个元素变量进行存取操作。
     # include <iostream.h>
          void main( void)
          { int a[5]={0,1,2,3,4},i,j,*p,n=5;
            p=a;
            for (i=0;i<n;i++) 
             { cout <<*p<<'\t'; 
              p++;
             } 
            cout<<endl;
            p=a;
            for (i=0;i<n;i++) cout <<*(p+i)<< '\t'; 
            cout<<endl;
            for (i=0;i<n;i++) cout <<*(a+i)<< '\t';
            cout<<endl;
            for (i=0;i<n;i++) cout <<p[i]<< '\t';
            cout<<endl;
          }
       执行程序后,输出:
       0 1 2 3 4
       0 1 2 3 4
       0 1 2 3 4
       0 1 2 3 4
 (1)通过移动指针变量,依次访问数组元素。如:
           p=a; 
           for (i=0;i<n;i++) 
           { cout <<*p<<'\t'; p++;}
       首先将指针变量p指向数组a的首地址。然后用*p输出数组第i个元素的值,每次输出后用p++移动指针到下一个元素,依次循环直到结束。
       注意:cout<<*p<<'\t'; p++;可合并为一条语句:cout<<*p++<<'\t';

 (2)指针变量不变,用p+i或 a+i 访问数组第i个元素。如:
    for (i=0;i<n;i++) cout <<*(p+i)<< '\t'; 
           for (i=0;i<n;i++) cout <<*(a+i)<< '\t';
       在C++中允许用p+i 或a+i 表示第i 个元素的地址。因此,*(p+i)与*(a+i)均表示第i个元素的内容。

 (3)以指针变量名作为数组名访问数组元素。如:
    for (i=0;i<n;i++) cout <<p[i]<< '\t';       
若用指针变量名p作为数组名,则p[i]表示数组的第i个元素a[i]
* 数组元素的引用

      综上所述,对一维数组a[ ]而言,当p=a后,有如下等同关系成立:
      ① p+i=a+i=&a[i],即p+i、a+i 均表示第i个元素的地址&a[i]。
      ② *(p+i) =*(a+i)=p[i]= a[i]。即*(p+i), *(a+i), p[i]均表示第i个元素值a[i]。
      其中p[i] 的运行效率最高。
      由上所述可知:一维数组的第i个元素可用四种方式引用,即: a[i]、*(p+i) 、*(a+i)、p[i]。

2.二维数组与指针

*  二维数组元素在内存中的存放方式

 在C++中,二维数组元素值在内存中是按行的顺序存放的。


* 二维数组行首地址

      二维数组各元素按行排列可写成
      a[0]=(a[0][0],a[0][1],a[0][2])
      a[1]=(a[1][0],a[1][1],a[1][2])
      a[2]=(a[2][0],a[2][1],a[2][2])
      因为数组名可用来表示数组的首地址,所以一维数组名a[i]可表示一维数组 (a[i][0],a[i][1],a[i][2])的首地址&a[i][0],
      即可表示第i行元素的首地址。

* 二维数组行地址 

    为了区别数组指针与指向一维数组的指针,C++引入了行地址的概念,并规定二维数组a中第i行地址用a+i或&a[i]表示,
      行地址的值与行首地址的值是相同的,即:
      a+i=&a[i]=a[i]=&a[i][0]
      但两者类型不同,所以行地址a+i与&a[i]只能用于指向一维数组的指针变量,而不能用于普通指针变量,例如:
      int a[3][3];
      int *p=a+0;
      则编译第二条指令时将会出错,编译系统提示用户p与a+0的类型不同。如果要将行地址赋数组指针变量,必须用强制类型转换,如:
      int *p=(int *) (a+0);
      二维数组名a可用于表示二维数组的首地址,但C++规定该首地址并不是二维数组中第0行第0列的地址(即a≠a[0][0]),
      而是第0 行的行地址,即a=a+0=&a[0]。

* 二维数组的元素地址与元素值

      知道了二维数组的行地址与行首地址后,可以讨论二维数组的元素地址。
      因为 a[i]=*&a[i]= *(a+i),所以 *(a+i) 可以表示第 i行的首地址。因此二维数组第i行首地址有三种表示方法:a[i] 、*(a+i)、&a[i][0]。
      由此可推知:第i行第j列元素a[i][j]的地址有四种表示方法:
      a[i]+j 、*(a+i)+j、&a[i][0]+j、&a[i][j]
      第i行行地址 a+i、&a[i]
      第i行首地址(第i行第0列地址) a[i]、 *(a+i)、 &a[i][0]
      元素a[i][j]的地址 a[i]+j 、*(a+i)+j 、&a[i][0]+j、&a[i][j]
      第i行第j列元素值 *(a[i]+j) 、 *(*(a+i)+j) 、 *(&a[i][0]+j)、a[i][j]
      最后总结例子:
     # include <iostream.h>
          void main(void)
          { 
               int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
                 for (int i=0;i<3;i++)
                   { 
                     cout<<"&a["<<i<<"]="<<&a[i]<<"="<<a+i<<endl; //输出第i行行地址
                     cout<<"a["<<i<<"]="<<a[i]<<"="<<*(a+i)<<"="<<&a[i][0]<<endl; //行首地址
                      for (int j=0;j<3;j++)
                        { cout<<"&a["<<i<<"]["<<j<<"]="<<a[i]+j<<"="<<*(a+i)+j<<"="<<
                              &a[i][0]+j<<"="<<&a[i][j]<<endl; //输出元素a[i][j]的地址
                          cout<<"a["<<i<<"]["<<j<<"]="<<*(a[i]+j)<<"="<<*(*(a+i)+j)<<
                                "="<<*(&a[i][0]+j)<<"="<<a[i][j]<<endl; //输出元素a[i][j]的值
                        }
                   } 
          }
          程序执行后输出结果为:
            &a[0]= 0x0065FDD4=0x0065FDD4
            a[0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4
            &a[0][0]= 0x0065FDD4=0x0065FDD4=0x0065FDD4=0x0065FDD4
            a[0][0]=1=1=1=1
            &a[0][1]= 0x0065FDD8=0x0065FDD8=0x0065FDD8=0x0065FDD8
            a[0][1]=2=2=2=2
            &a[0][2]= 0x0065FDDC=0x0065FDDC=0x0065FDDC=0x0065FDDC
            a[0][2]=3=3=3=3
            &a[1]= 0x0065FDE0=0x0065FDE0
            a[1]= 0x0065FDE0=0x0065FDE0=0x0065FDE0
            &a[1][0]= 0x0065FDE0=0x0065FDE0=0x0065FDE0=0x0065FDE0
            a[1][0]=4=4=4=4
            &a[1][1]= 0x0065FDE4=0x0065FDE4=0x0065FDE4=0x0065FDE4
            a[1][1]=5=5=5=5
            &a[1][2]= 0x0065FDE8=0x0065FDE8=0x0065FDE8=0x0065FDE8
            a[1][2]=6=6=6=6
            &a[2]= 0x0065FDEC=0x0065FDEC
            a[2]= 0x0065FDEC=0x0065FDEC=0x0065FDEC
            &a[2][0]= 0x0065FDEC=0x0065FDEC=0x0065FDEC=0x0065FDEC
            a[2][0]=7=7=7=7
            &a[2][1]= 0x0065FDF0=0x0065FDF0=0x0065FDF0=0x0065FDF0
            a[2][1]=8=8=8=8
            &a[2][2]= 0x0065FDF4=0x0065FDF4=0x0065FDF4=0x0065FDF4
            a[2][2]=9=9=9=9
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值