第22课 - 数组基础
1. 数组的概念
数组是相同数据类型的变量的有序集合。
- 数组的大小
数组在一片连续的内存空间中存储元素。
数组元素的个数可以显示或隐式指定。
eg:
int a[5] = {1, 2}; //指定长度为5,后3个元素编译器初始化为0
int b[] = {1, 2}; //隐式指定长度为2
- 数组地址与数组名
(1)数组名代表数组首元素的地址。
(2)数组的地址需要用取地址符&才能得到。
(3)数组首元素的地址值与数组的地址值相同。但数组首元素的地址与数组的地址是两个不同的概念。
- 数组名的盲点
(1)数组名可以看做一个常量指针。
(2)数组名“指向”的是内存中数组首元素的起始位置。
(3)在表达式中数组名只能作为右值使用。
(4)只有在下列场合中数组名不能看做常量指针:
l 数组名作为sizeof操作符的参数。
l 数组名作为&运算符的参数。
l 数组名其实并不是指针,在外部声明时不能混淆。
例程:
#include <stdio.h>
// another file
// char* p = "Hello World!";
extern char p[];
int main()
{
printf("%s\n", p);
return 0;
}
我们在另有一个文件中,初始化了我们的指针p。但是在linux下运行这个程序,我们发现结果是乱码。下面我们分析一下。当我们初始化指着p时,就会创建一个符号表,如下:
p |
char |
4个字节 |
指向的地址 |
当遇到命令extern char p[];时,我们就会从符号表中找到p,把p指向的地址打印出来。
注:编译器处理指针与数组的区别
l 处理指针:一次寻址操作。p中存的是地址,我们要把它指向的地址找出来。
l 处理数组:无寻址。p开始就存的是我们要的数,不用寻址。
我们要是将上个文件做一定的改变,同样可以行得通。
#include <stdio.h>
// another file
// char* p = "Hello World!";
extern char p[];
int main()
{
printf("%s\n", (char*)(*((unsigned int *)p)));
return 0;
}
可以得到预期结果。(unsigned int *)p将数组p装换成指针,但是它所指的是首地址,并不是内容,*((unsigned int *)p)前加*表示钥匙打开,取其中的存储内容,(char*)(*((unsigned int *)p))是前面又加了(char)表示将其中读取的内容当做指针,读取指针所指的内容。
小结:
l 数组是一片连续的内存空间
l 数组的地址和数组首元素地址意义不同
l 数组名大多数情况下被当做常量指针处理
l 数组名其实并不是指针,在外部声明时不能混淆