指针问题小结

来源:互联网 发布:h3c交换机端口速率 编辑:程序博客网 时间:2024/06/10 08:45

最近几天复习了一下指针,总结记录一下。

区分几个概念:

指针数组:指针的数组,即本质是一个数组,数组的每一个元素是一个指针。

数组指针:数组的指针,即本质是一个指针,指针指向的对象必须是一个数组。

指针函数:返回指针的函数,本质是一个函数,返回类型是一个指针

函数指针:本事是一个指针变量,指向的是一个函数的地址。

 

int *p[]指针数组,int(*p)[]数组指针,int**p双指针,int p[][]二维数组的比较

首先看一下二维数组的内存分配情况

 

 

 


其内存是连续的,也就是说知道第一个地址就能推算出任一一个元素的地址。对于一个二维数组int[m][n]

&P[i][j]=&P[0][0]+(i*n+j)*sizeof(int *);所以sizeof(p)= m*n*sizeof(int *);

定义一个二维数组。可以看出h[0]是一个数组的首地址,而不是一个数组第一个元素的地址。


Sizeof(h[i]) = n*sizeof(int *)

int *p[]是一个指针数组,其内存分配情况如下图所示。

 

p[i]之间是连续的,即&p[i]=p[0]+sizeof(int*)*i;但是&p[i][0],&p[i+1][0]之间是不连续的。也就是说&p[i+1][0]!= &p[i][0] + n*sizeof(int );sizeof(p) = n*sizeof(int* );和二维数组的大小不一样。

看个例子

int a[6]={1,2,3,4,5,6};

int b[6]={6,5,4,3,2,1};

int*c[6];

c[0] = a;

c[1] = b;

调试结果如下:


C是一个数组,有六个元素。第一个和第二个元素赋值,后面四个没有赋值。并且C[0],C[1]并没有指向一个数组地址,获得数组的所有元素,而是指向了数组的第一个元素。即代码C[0]= a 等价于 C[0] =&a[0].虽然可以使用C[0][1]访问a[1],但是C的内存不是连续的。

int m = 0;

int n = 1;  

c[0] = &m;

c[1] = &n;


从这段代码可以看出可以通过c[i][j]访问二维数组,是通过地址计算得到的,每个c[i]的值是数组的首地址,而不是整个个数组。

Sizeof(c[i]) = sizeof(int *)。一个指针的地址大小

数组指针

数组指针的内存分配情况和二维数组一样,连续分配地址控件。通常用于二维数组在不知道有多少行的情况下的动态二维数组。

Int (*p)[6] = new int [n][6]

int (*p)[6]:数组指针,该数组需要有一个特点:必须有6列。P赋值后p[i]的值都确定了。P[i]=p[0]+i*n*sizeof(int)

 

Int (*d)[6] = h;


可以看出d[i]之间的关系为d[i] = d[0]+i*6*sizeof(int )

P是一个指针所有sizeof(p)= sizeof(int * );sizeof(p[i]) = sizeof(int )*n;

数组指针通常用于二维数组的的参数传递。

 

可以把指针数组强制转换为数组指针,数组指针不能强制转换为指针数组。

d = (int(*)[6])c;//强制转换为数组指针

这样就是把c看出了一个有留个元素的一维数组,知识这个数组的值时地址,但是强制转换后c[0]的地址值,并看成了整数。其中0x0012fee8 = 1244904。就像int  testp = (int)p一样。

这样的结果是

 

int **p是一个二重指针。也可以使用p[i][j]的形式来访问二维数组。尤其是在不知道二维数组的行和列的情况下使用动态的二维数组

         int **i = new int *[3];

         for(int index =0;index<3;index++)

         {

                   i[index]=new int[6];

         }


可以看出这实际上指向的是二维数组的第一个元素的地址的地址。类似于动态一维数组

int *f = newint[6];

f=a;


所以sizeof(i) = sizeof(int **),sizeof(i[index]) = sizeof(int *),并且在堆上的内存分配不似二维数组的分配。更类似于指针数组的分配。

指针数组可以直接赋值给二重指针。从动态二维数组可以看出,二者本质差不多。

数组指针可以强制转换为二重指针,但是转换后结果是这样的:

i =(int **)d;

i= (int **)h


不能以i[m][n]的形式访问,这样的话就意味着二维数组的参数传递不能传给二重指针。这个原因是什么呢?看下面这三条语句:

         i = (int **)d[0];

         i = (int **)&d[0][0];

         i = (int **)*d;

这三条语句实际上是一样的。因为d[0]=&d[0][0]=*d;

这三条产生上述的结果是可以理解的上面说过,int *可以强制转换为int,同样int 也可以强制转换为int*;这样强制转换过之后就将d[0][0]的值强制转换成了地址,所以i[0]的值就是的d[0][0]的值了。但是这三条语句为什么和i =(int **)d;是一样的呢?我们知道一维数组a,至少有两种含义,1是数组的首地址,2是数组第一个元素的地址。这个时候d的值和的d[0]的值是一样的,代表的是数组第一个元素的地址。所以强制赋值之后不能使用i[m][n]去访问d数组了。可以看到i+1实际上及时d[1]的值了。

使用i+1,i[]等符号是,必须知道i的类型,根据类型移动适当的字节。举个例子

void *x=malloc(4);

int *xx = (int*)malloc(4);


当不指明类型是,x+1,x[0],是没有意义的。不知道要加多少个地址。所以在指针数组中,c+1=c+sizeof(int *), d+1=d+sizeof(int)*n;

 



0 0
原创粉丝点击