bodu.com

电子/电气工程师博客

正文 更多文章

指针数组和数组指针

                         指针数组和数组指针

 

                            王佰营  徐丽红

一、名字不同

数组是一些类型相同的数据的集合,每个数组元素均占有相同长度的内存区;

指针数组是存放指针变量的数组,其每个元素都是一个指针变量;

数组指针是一个指向数组的指针,这个指针指向的是一个在内存中有连续地址分配的数组。

二、定义不同

数组的定义:    char ch_arr[8];

指针数组的定义:char *ar_of_p[3];等价于char *(ar_of_p[3]);

数组指针的定义:char (*p_of_ar)[10];

三、分析原则

学习数组、指针必须把握两点:

1、  时刻和内存联系起来;变量都是和内存单元相对应;

2、  时刻注意变量的基类型;变量间传输数据需要其基类型匹配;

四、实例分析

1、  数组

char ch_arr[8];

数组名ch_arr实际上就是代表该数组在内存中开始存放数据的地址,是一个不可改变的地址常量;不能像一般变量那样作诸如ch_arr++,ch_arr--,ch_arr += ……的运算。数组名ch_arr的值为&ch_arr [0]& ch_arr [0]为字符型数组ch_arr [8]的第一个元素的地址;

如果执行:      

printf("ch_arr =%d;\n, ch_arr [0] =%d\n",ar1,&ar1[0]);

执行结果为:ch_arr   =1245028;

ch_arr [0]=1245028

注意:当涉及到地址时,不同的计算机执行结果会不同,以后不在提示;

2、指针变量

指针变量的实质就是分配用来专门存放地址的内存单元;比如凡是内存中分配为存放int型数据的单元的地址就可放入int型指针变量;如:

int *pint,  iTemp = 200;

pint = &iTemp;

如果执行:

       printf("&pint=%d;\n pint=%d;\n *pint=%d;\n &iTem=%d; \n iTem=%d; \n ",

&pint,pint,*pint,&iTem,iTem);

执行结果为:

&pint  = 124496;// 分配用来专门存放地址的内存单元;

pint    =124492;// pint中存的是item变量的地址;

*pint   =200;   // pint所指向124492单元中存的数据;

&item  =124492; //item变量在内存中分配的地址;

item  =200;   //item变量的中存放的数据;

3、指针数组

指针数组是存放指针变量的数组,其每个元素都是一个指针变量,也就是这个数组在内存中开辟的区域存放的都是地址。

如果执行:

              int *ar_of_p[3];     //指针数组的定义;

              int iTem1 = 100, iTem2 = 200, iTem3 = 300;

              ar_of_p[0] = & iTem1 ;

              ar_of_p[1] = & iTem2 ;

              ar_of_p[2] = & iTem3 ;

              printf("&iTem1=%d;\n iTem1=%d;\n",&iTem1,iTem1);

              printf("&ar_of_p[0]=%d;\n ar_of_p[0]=%d;\n *ar_of_p[0]=%d; \n \n ",

&ar_of_p[0],ar_of_p[0],*ar_of_p[0]);

 

              printf("&iTem2=%d;\n iTem2=%d;\n",&iTem2,iTem2);

              printf("&ar_of_p[1]=%d;\n ar_of_p[1]=%d;\n *ar_of_p[1]=%d; \n\n ",

&ar_of_p[1],ar_of_p[1],*ar_of_p[1]);

 

              printf("&iTem3=%d;\n iTem3=%d;\n",&iTem3,iTem3);

              printf("&ar_of_p[2]=%d;\n ar_of_p[2]=%d;\n *ar_of_p[2]=%d; \n\n ",

&ar_of_p[2],ar_of_p[2],*ar_of_p[2]);

执行结果为:

        &iTem1 = 1245040;// 给变量iTem1在内存中分配的地址;

          iTem1 = 100;    //iTem1变量的中存放的数据

     &ar_of_p[0] = 1245044; //给元素ar_of_p[0]在内存中分配的地址;

       ar_of_p[0] = 1245040; ar_of_p[0]中存的是iTem1在内存中分配的地址

      *ar_of_p[0] = 100; //*ar_of_p[0]所指向1245040单元中存的数据;

 

        &iTem2=  1245036; // 给变量iTem2在内存中分配的地址;

          iTem2 = 200;    //iTem2变量的中存放的数据

     &ar_of_p[1] = 1245048;//给元素ar_of_p[0]在内存中分配的地址;

       ar_of_p[1] = 1245036; ar_of_p[1]中存的是iTem2在内存中分配的地址

      *ar_of_p[1] = 200; //*ar_of_p[1]所指向1245036单元中存的数据;

 

        &iTem3=  1245032; // 给变量iTem3在内存中分配的地址;

          iTem3 = 300;    //iTem3变量的中存放的数据

     &ar_of_p[2] = 1245052; //给元素ar_of_p[0]在内存中分配的地址;

       ar_of_p[2] = 1245032;// ar_of_p[2]中存的是iTem2在内存中分配的地址

      *ar_of_p[2] = 300; //*ar_of_p[2]所指向1245032单元中存的数据;

4、数组指针

    我们先看一个程序:

       int ( *pArr)[3];

          int iAr[3];

          int iArr[2][3];

          pArr=iArr;

          pArr = iArr+1;

          pArr = iAr;//此句不能编译通过

为什么pArr = iAr;编译出错?

错误提示为:

error C2440: ’=’ : cannot convert from ’int [3]’ to ’int (*)[3]’

  pArr=iArr;

       pArr = iArr+1;

就可编译通过呢?

再看程序:

               printf("iAr=%d;\n iAr+1=%d;\n iAr+2=%d;\n\n",

iAr,iAr+1,iAr+2);

               printf("iArr=%d;\n iArr+1=%d;\n \n ",

iArr,iArr+1);

            printf("sizeof(int)=%d;\n ",sizeof(int));

执行结果为:

         iAr  = 1245040;

         iAr+1 = 1245044;

         iAr+2 = 1245048;//间隔为4

 

         iArr  = 1245016;

         iArr+1 = 1245028;//间隔为12=4×3

 

         sizeof(int) = 4;

     上边的执行结果可知:

           编译器将二维数组int iArr[2][3]按含有两个元素的一维数组对待,并且每个元素的基类为 4×3 = 12个内存存储单元(3int变量所占)的数据来看待;那么&iArr[0]iArr就表示可存放3int型变量(12个存储单元)的一段内存的首地址。

iAr[3]虽然是可存放3int变量的元素的数组,但是每个元素的基类型为int; iArr[0]的基类型为占用12个存储单元的数据类型;显然,数组指针是一个指向数组的指针,这个指针指向的是一个在内存中有连续地址分配的数组。它的数据类型是由连续分配的内存数决定的,作为一个整体看待的。int ( *pArr)[3]表示:pArr是一个指向含有3个整型元素的一维数组的指针,其基类型为占用(3×sizeof(int) =)12个存储单元的数据类型既然如此,

   若定义:

int ( *pArr)[3];

int iArr[2][3];

int iAr[3];

那么:

以下基类型是匹配的,也是正确的:

pArr = iArr;

 pArr = &iArr[0];

pArr = iArr+1;

 pArr = &iArr[1];

以下基类型是不匹配的,是错误的:

pArr = iAr; 

 pArr = &iAr[0];

       我们进一步看编译器是如何处理数组指针的,请看下面的程序:

int towArr[2][3]={{1,2,3},{10,20,30}};

int (*ptr)[3];

int arr[3] = {100,200,300};

int *p=arr;

ptr = towArr;

printf("ptr         =%d\n",ptr);

printf("ptr+1     =%d\n\n",ptr+1);

 

printf("*ptr    = %d\n",*ptr);

printf("*ptr+1  = %d\n",*ptr+1);

printf("*ptr+2  = %d\n\n",*ptr+2);

 

printf("**ptr      = %d\n",*ptr);

printf("*(*ptr+1)= %d\n",*(*ptr+1));

printf("*(*ptr+2)= %d\n\n",*(*ptr+2));

 

printf("p           = %d\n",p);

printf("*p         = %d\n",*p);

printf("p+1       = %d\n",p+1);

printf("*(p+1)   = %d\n\n",*(p+1));

 

执行结果:

ptr       = 1245032;   //基类型为12个字节;

ptr+1   = 1245044;   //+12

 

*ptr      = 1234032;  // 基类型为4个字节;

*ptr+1  = 1235036;  //+4

*ptr+2  = 1245040;  //+4

 

**ptr      = 1;     // towArr[0][0]的值;

*(*ptr+1)= 2;    // towArr[0][1]的值;

*(*ptr+2)= 3;    // towArr[0][2]的值;

 

p           = 1245004;  //与数组指针的处理方式不同;

*p          = 100; 

p+1        = 1245008;

*(p+1)    = 200;

可见,与p的处理方式不同,数组指针的(*ptr)和ptr的值均为地址1245032,但是它们的基类型已经不同了:

ptr 的基类型为占用12个字节存储单元的数据类型;

*ptr的基类型为占用4个字节存储单元的数据类型;

 

那么:

**(ptr+1)              就是towArr[1][0]的值:10

**(ptr+1)+1 就是towArr[1][1]的值:20

**(ptr+1)+2 就是towArr[1][2]的值:30

编程运行结果确实如此.

 

 

 

分享到:

上一篇:学习技术心得

下一篇:

评论 (1条) 发表评论

发表评论
验证码