int a[5] = {1,2,3,4,5};
1,&a[0]和&a a[0]是一个元素,a是整个数组,虽然&a[0]和&a的值是一样的,但其意义不同,前者是数组首元素的地址,后者是数组的首地址
2,数组名作为左右和右值的区别。
a作为右值时的意义与&a[0]的意义是一样的,代表的是数组首元素的首地址,而不是数组的首地址。但是要注意,这仅仅是代表,并没有一个地址来存储这个地址,这点跟指针有很大的差别。
a不能作为左值,我们可以把a[i]当左值,而无法把a当左值。
3,a和&a的区别
a,&a的值是一样的,但意思不一样,a是数组首元素的首地址,也就是a[0]的首地址,&a是数组的首地址,a+1是数组下一元素的首地址,即a[1]的首地址,&a+1是下一个数组的首地址;这也就是*(a+1)和*(&a+1)的区别所在。
弦外之音:对于指针移动加1操作,得到的是下一个元素的地址,而不是源地址直接加1。所以一个类型为T的指针的移动,以sizeof(T)为移动单位。
4,指针和数组
指针和数组之间没有任何关系!!!只是相似罢了。
指针就是指针,指针变量在32位系统下,永远站4个byte,其值为某一个内存的地址。指针可以执行任何地方,但是不是任何地方你都可以通过这个指针变量访问的到的。
数组就是数组,其大小与元素个数和元素类型有关,定义数组时必须制定其类型和个数,数组可以存任何了性的数据,但不能存储函数。
再来点弦外之音===【指针和数组的声明】:
(1)定义为数组,声明为指针。
文件1中定义: char a[100];
文件2中声明如下: extern char *a;
定义分配内存,而声名没有,定义只能出现一次,而声名可以出现多次,我们知道如果编译器需要某个地址来执行某种操作的话,他就可以直接通过开锁动作(使用“*”着把钥匙)来读或者写这个地址上的的内存,并不需要去找到储存这个地址的地方。相反对于指针而言,必须先去找到储存这个地址的地方,取出这个地址值然后对这个地址进行开锁(使用“*”这把钥匙);
这就是为什么extern char a[]与extern char a[100]等价的原因,因为这只是声明,不分配空间,所以编译器无需知道这个数组有多少个元素。这两个声明都告诉编译器a是在别的文件中被定义的一个数组,a同是代表着数组a的首元素的首地址,也就是这快内存的起始地址。数组内的任何元素的地址都只需要知道这个地址就可以计算出来。
当你声明extern char *a;时,虽然在文件1中,编译器知道a是一个数组,但是在文件2中,编译器并不知道这点,大多数的编译器是按照文件分别编译的,编译器只按照本文件中声明的类型来处理。所以,虽然a实际大小为100个byte,但是在文件2中,编译器认为a只占4个byte。
(2)定义为指针,声明为数组
既是如果在文件1中定义为指针,而在文件中声明为数组也会发生错误。
5,指针间接访问数据,首先取得指针变量p的内容,把它作为地址,然后从这个地址提取数据或者向这个地址写入数据。
指针可以以指针的形式访问*(p+i),也可以以下标的形式访问p[i]。但其本质都是先去p的内容然后加上i*sizeof(类型)
个byte作为数据的真正地址。
数组也可以以指针的形势访问*(a+i);也可以以下标的形势访问a[i]。但本质都是a所代表的数组首元素的首地址
加上i*sizeof(类型)个byte作为数据的真正地址。
阅读(786) | 评论(1) | 转发(1) |