数组、指针、指针数组、数组指针(转)

来源:互联网 发布:欧洲卡车模拟 mac 编辑:程序博客网 时间:2024/05/21 03:25

数组、指针、指针数组、数组指针

分类: C/C++ 笔试面试 149人阅读 评论(0) 收藏 举报

(1数组类型到指针类型转换的结果,数组名不再代表数组对象,而是一个代表数组首地址的符号地址,并且不是对象。特别指出的是数组到指针的转换规则只适用于表达式,只在这种条件下数组名才作为转换的结果代表数组的首地址而当数组名作为数组对象定义的标识符、初始化器及作为sizeof、&的操作数时,它才代表数组对象本身,并不是地址。

       这种转换带来一个好处,对于数组内部的指针运算非常有利。我们可以用a + 1这种精炼的形式表示a[1]的地址(即:a+1等价于&a[1],无须用&a[1]这种丑陋的代码,实际上,&a[1]是一种代码冗余,是对代码的浪费,因为&a[1]等价于&*( a + 1 ),&与*由于作用相反被抵消,实际上就是a + 1,既然这样我们何不直接使用a + 1呢?撇开为了照顾人类阅读习惯而产生的可读性而言,&a[1]就是垃圾。

 

(2数组名不是指针,永远也不是,但在一定条件下,数组名可以转换为指针。


(3一维数组名理解为列指针;二维数组名理解为行指针。(深入理解)

一维数组:a+1表示第1列元素(从第0列算起)的首地址, 即a[1]的地址(&a[1]);

二维数组:a+1表示第1行元素(从第0行算起)的首地址,即a[1][0]的地址。


(4)*p++:指针所指向的位置不断加1,即指针指向发生变化,等价于*(p++),但这里由于是“后++”,因此,必须执行完整条语句后才会自加;这个语句等价于两条语句:首先*p;然后p++;

    (*p)++:不断加1,值发生变化;

    *++p:等价于*(++p),区别于第一条,这里是“先加加”,因此指针(地址)先变化,然后再取值变化后的地址对应的值;

    ++*p:等价于++(*p),值发生变化;

总结:按照“从右到左”顺序执行即可。


   a;  整个数组的首地址;

   &a: 数组首元素的首地址;以上两者虽然值相等,但是意义却不同。

   a+1;一维数组时,第1列元素(从第0列算起)的首地址;二维数组时,第1行元素(从第0行算起)的首地址;

&a+1不管是一维数组,还是二维数组, &a+1均表示下一个数组的首地址,此时“1” 相当于"1"个a大小的空间(偏移)。


另外,在下面的二维数组int a[3][4]中,要时刻注意“1”的单位问题

      a[0]+1:“1”的单位应该是两个字节(16位计算机),所以表示a[0][1]的地址;

       a+1:“1”的单位应该是4×2个字节(16位计算机),而不是2字节,所以表示a[1][0]的地址

 

问题:若 int a[4]; int* ptr = (int*)(&a+1); 则ptr含义是甚么 ?而ptr-1又表示什么 ?

答:&a+1如上图所示, 则ptr指向的是&a+1的位置。又ptr为int型的指针,故"ptr-1"则会减去"1"个int型指针的空间,即为a[4]的首地址。

 

(5二维数组元素的地址可以由表达式&a[i][j]求得;也可以通过每行的首地址来表示。

int a[3][4]中,地址&a[0][0]可以用a[0]+0来表示,地址&a[0][1]可以用a[0]+1表示;当0≤i<3、0≤j<4,则a数组元素可用以下五种表达式来引用: a[i][j]、*(a[i]+j)、*(*(a+i)+j)、(*(a+i))[j]、*(&a[0][0]+4*i+j)

 

(6指针数组,就是数组,只不过它是元素为指针(可理解为地址)的数组,为了便于理解,我把它理解为“指针型数组”,如int *b[4];

           数组指针,就是指针,只不过它是指向数组的指针,如int (*p)[4]。

int a[3][4];//二维数组,存储int型的数值,编译器为这个二维数组分配了3*4*sizeof(int)的连续空间 ;

int* b[4];//一维数组,存储int*型的数值,也就是人们常说的指针数组,该数组用来存储int型数据的地址,编译器为该一维数组分配了4*sizeof(int *)的空间 ;元素表示:*a[i]*(a[i])是一样的,因为[]优先级高于*

inta,b,c,d; 
b[0] = &a; b[1]= &b; b[2] = &c; b[3] = &d; 


int (*p)[4];//p是一个指向二维数组首地址的指针,并且这个二维数组低维的维数为4,也可理解为p指向一维数组,每个一维数组有4int元素。因此,编译器只是为p分配了一个指针的空间,在32位系统中,一般是4个字节。由于它不是一个数组,因此,编译器也不会为之分配数组空间。 元素表示:(*a)[i]  

int a[3][5];  int (*p)[4] = a;//错误,维数不匹配 

int a[3][4]; int (*p)[4] =a;//正确,你可以p[1][2]等来调用a中的元素,像用a[1][2]一样


int *p[n];  //[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1 p=a是错误的;因为p是个不可知的表示,只存在p[0]p[1]p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样*p=a;这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3]表示一个一维数组内存放着三个指针变量,分别是p[0]p[1]p[2]
所以要分别赋值。

 

int (*p)[n];  //p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //
该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //
将该二维数组的首地址赋给p,也就是a[0]&a[0][0]
 p++;       //
该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

 

7函数的传参

int (*p)[4]int p[][4],都是用来指向一个低维空间为4的二维数组的首地址。在函数的参数传递中,可见它们的效果是一样的。它们都只有一个指针的空间,因为他们只是用来记录一个数组的起始地址。

0 0
原创粉丝点击