鸡啄米这一讲继续给大家讲指针的知识,包括将指针用于数组元素的处理和指针数组。

       一.指向指针元素的指针 

       前面说过,数组是有一定顺序关系的数组元素的集合,数组元素在内存中的存储地址是连续的。指针的加减运算特别适合处理这种存储在连续内存空间内的相同类型的数据,我们可以用指针方便的来处理数组元素的运算。

       假设有一个声明:int a[10];,声明了一个一维整型数组,有10个元素。数组名a代表了数组a的首地址,它是一个指针常量,也就是不能改变,所以,注意,不能进行自增自减运算。首地址就是数组第一个元素的地址,所以a和&a[0]是完全等价的。a中的10个元素是连续存放在内存中的,所以用数组名结合简单的算术运算就可以访问数组的元素。a是数组第一个元素的地址,那么第i+1个元素也就是下标为i的元素的地址就是a+i,第i+1个元素就是*(a+i)。例如,*a就是a[0],*(a+7)就是a[7]。

       鸡啄米结合前面跟这一讲的内容给大家三种访问数组元素的方式的例子:

       1.使用数组名和下标访问的方式

         int main()
         {
               int a[5];
               int i;
               for(i=0; i<5; i++)
                     cin>>a[i];
               cout<<endl;
               for(i=0; i<5; i++)
                     cout<<a[i]<<"  ";
               return 0;
        }

       2.使用数组名和指针运算访问的方式

        int main()
        {
              int a[5];
              int i;
              for(i=0; i<5; i++)
                    cin>>a[i];
              cout<<endl;
              for(i=0; i<5; i++)
                    cout<<*(a+i)<<"  ";
              return 0;
        }

       3.使用指针变量访问的方式

        int main()
        {
               int a[5];
               int *p;
               int i;
               for(i=0; i<5; i++)
                       cin>>a[i];
               cout<<endl;
               for(p=a; p<(a+5); p++)
                       cout<<*p<<"  ";
               return 0;
        }

 

鸡啄米:C++编程入门系列之二十九(数组、指针和字符串:指向数组元素的指针和指针数组)

       这几个例子很简单,鸡啄米就是让大家了解下几种访问数组元素的方式,大家在不同的情况下可以灵活运用。上面3个程序都是让用户先输入5个元素存入数组a,然后顺序输出。

       二.指针数组

       前面鸡啄米讲到的数组中的元素或者是基本类型的变量或者是类的对象,同理,数组元素也可以是指针变量,而且每个指针变量的类型是相同的,这样的数组就是指针数组。

       声明一维指针数组的语法形式是:数据类型 *数组名[下标表达式];。

       数据类型指明指针数组元素的类型,就是确定每个元素指针指向什么类型的数据。数组名也是这个指针数组的首地址。下标表达式指明数组元素的个数。

       比如,int *p[5];声明了一个整型指针数组,有5个元素。其中每个元素都指向整型数据。指针数组的每个元素都是指针,所以也需要先赋值才可以引用。

       鸡啄米再给大家一个用指针数组输出两个一般数组的数据的例子:

         #include <iostream>
         using namespace std;
         int main()
         { 
                int array1[]={1,2,3};//声明一个数组
                int array2[]={2,4,6};//声明另一个数组
                int *p[2];      //声明整型指针数组
                p[0]=array1;         //初始化指针数组元素
                p[1]=array2;
                //输出两个数组的全部元素
                for(int i=0;i<2;i++)     //对指针数组元素循环
                {
                         for(int j=0;j<3;j++)//对每个一般数组循环
                         {
                                cout<<p[i][j]<<" ";
                         }
                         cout<<endl;
                }
                return 0;
         }

       上面的程序中先声明了两个整型数组array1和array2,然后又声明了一个整型指针数组p,使p的两个元素分别指向数组array1和array2。p[0]就指向array1,那么p[0][0]就是array1[0],p[0][1]就是array1[1],p[0][2]就是array1[2],p[1]同理。这样利用指针数组的元素就可以访问数组array1和array2的数据并输出。程序运行结果是:

       1 2 3
       2 4 6

       二维数组在内存中是按照行优先的方式顺序存放的,所以二维数组我们可以理解为一维指针数组,每个指针元素分别指向二维数组的一行,这个一维指针数组的元素个数就是二维数组的行数。

       例如有一个二维数组:int array[2][3]={{1,2,3},{2,4,6}};。这是一个两行三列的二维数组,它就相当于一个一维整型指针数组,指针数组的元素个数就是二维数组array的行数2,等价指针数组的两个元素可以表示为array[0]和array[1],分别代表了二维数组array第0行和第1行的首地址,而array的每一行就相当于有3个元素的一维整形数组。

       大家来看一个二维数组输出的例子:

        #include <iostream>
        using namespace std;
        int main()
        { 
                  int array[2][3]={{1,2,3},{2,4,6}};
                  for(int i=0;i<2;i++)
                  {  
                            for(int j=0;j<3;j++)
                            {  
                                      cout<<*(*(array+i)+j)<<" ";   
                                      //也可以是 cout<<array2[i][j]<<" ";
                            } 
                            cout<<endl;
                  }
                  return 0;
        }

       程序运行结果是:

       1 2 3
       2 4 6

       用数组指针访问二维数组元素的方式是:*(*(array+i)+j)。怎样理解这个表达式呢?array是它的等价指针数组的首地址,那么array+i就是第i(基数是0)个指针元素,联系上面讲的,它指向的是二维数组的第i行的首地址,*(array+i)则是二维数组第i行的首地址,*(array+i)+j就是二维数组第i行第j(基数是0)个元素的地址,所以*(*(array+i)+j)就是二维数组array第i行的第j个元素的值了。

      指针数组可能有点难理解,大家多看几遍,思考思考,其实还是很清楚的。鸡啄米这一讲就讲这么多了,有问题欢迎到鸡啄米博客留言交流。