1. 数组的概念
(1)数组是相同类型的变量的有序集合
(2)数组在一片连续的内存空间中存储元素
(3)数组元素的个数可以显示或隐式指定
【编程实验】数组的初始化
#include <stdio.h> int main(){ //数组初始化 int a[5] = {1, 2};//第1、2个元素分别为1、2,其余为0 int b[] = {1, 2};//编译过程中,编译会为计算数组b的大小 int i=0; for (i = 0;i < 4;i++) { printf("a[%d] = %d\n",i,a[i]); } printf("sizeof(a) = %d\n",sizeof(a)); //20 printf("sizeof(b) = %d\n",sizeof(b)); //8 printf("count for a: %d\n",sizeof(a)/sizeof(int)); //5 printf("count for b: %d\n",sizeof(b)/sizeof(int)); //2 return 0; }
2. 数组地址(&a)与数组名a
(1)数组名a代表数组首元素的地址。因此,第2个元素的地址为a+1,以此类推……。注意a或a+i表示元素的地址。可以用*(a+i)取出元素的值,也可以用a[i]来取出元素的值,因为当编译中遇到a[i]会自动转为*(a+i)。反过来也可知,第1个元素的地址为a或&a[0],第2个元素的地址为a+1或&a[1],第i个元素的地址为(a+i)或&a[i]……
(2)数组的地址需要用取地址符&才能得到。即形如&a取的是整个数组的地址,所以&a+1表示指向整个数组的最后面的位置。
(3)数组的首元素的地址值与数组的地址值相同,但是两个不同的概念。
【编程实验】数组名和数组地址
#include <stdio.h> int main(){ //将数组每个元素初始化为0 int a[5] = {0};//含义,将第1个元素初始化为0,其余为0. printf("a = %p\n",a); //首元素的地址 printf("&a = %p\n",&a); //整个数组的地址,从数值与看,与a一样。 printf("&a[0] = %p\n",&a[0]);//第1个元素的地址 return 0; }
3. 数组名的盲点
(1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组。如int a[5]表示a的类型为int[5],所以sizeof(a)表示取整个数组的大小,&a表示数组的地址。
(3)数组名的外延:除了sizeof(a)和&a外,数组名经常被可看作是一个常量指针。但要注意这里仅仅是“看作”,而不是真正的指针。不同于指针,数组名只是编译过程中的一个符号,编译器并不为其分配内存,有人称之为“伪变量”。因此,形式a++\a—或a=b(其中b是另一个数组名)这些都是错误的,因为a只是一个符号,编译器会把数组信息(如大小,地址)放入符号表中,每次遇到数组名a时,就会从符号表中取出这个数组的地址,然后用这个固定的地址代替 a,所以这个符号并没有被分配内存空间,而上述操作都是针对变量而言的,故数组名只能做为右值使用。
(4)对数组的引用,如a[i]或*(a+i),只需访问内存一次,而指针的引用如*(p+i)则需要两次,首选通过&p找到p指针,然后加i,再从p+i里面取出的内容。
(5)当数组名作为形参时,将退化为指针。即可以把数组名当成指针来用,这里的sizeof(数组名)为4,即指针的长度。
【实例分析】数组和指针并不相同
#include <stdio.h> int main(){ //将数组每个元素初始化为0 int a[5] = {0}; int b[2]; int* p = NULL; p = a; printf("a = %p\n",a); //首元素的地址 printf("p = %p\n",p); //p==a。 printf("&p = %p\n",&p);//指针p的地址 printf("sizeof(a) = %d\n",sizeof(a));//数组的大小:20 printf("sizeof(p) = %d\n",sizeof(p));//指针的大小为4. printf("\n"); p = b; printf("b = %p\n",b); //首元素的地址 printf("p = %p\n",p); //p==b。 printf("&p = %p\n",&p);//指针p的地址 printf("sizeof(b) = %d\n",sizeof(b));//数组的大小:8 printf("sizeof(p) = %d\n",sizeof(p));//指针的大小为4. //a = b; //编译错误,数组名不能作为左值; //a++; //编译错误,数组名被编译一个固定地址,相当于0xaabbccdd++的错误 return 0; }
4. 小结
(1)数组是一片连续的内存空间
(2)数组的地址和数组首元素的地址意义不同
(3)数组名在大多数情况下被当成常量指针处理
(4)数组名其实并不是指针,不能将其等同于指针。