一维数组与一级指针
首先,我们先从一维数组与一级指针开始这段艰涩的理解过程。
int a[3] = {1, 2, 3};
上面这段代码是我们所熟知的创建一维数组的方式,对于这段代码,我们需要知道的是,数组在内存中占有一片连续的存储空间,如图01所示。其次是,数组的变量名是数组中第一个元素的地址,即数组名既是一个变量名也是一个指针。
指针和指针变量严格来说是不一样的。对象的地址用于指示对象的存储位置,称为“指针”;而能够存放地址值得变量称为“指针类型的变量”,简称“指针变量”!
我们要关注的重点是数组变量名的含义。正如上面所说的,数组的变量名是数组中第一个数据的地址,即在上述代码中,a就是a[0]的地址,这点对于下面的理解至关重要(如图02所示)。
我们来看一下这段代码:
1 int a[3] = {1, 2, 3};
2 int *p;
3 p = a;
问题1:为什么一维数组变量名a能够赋值给一级指针p呢?
因为数组变量名a是数组中第一个数据的地址,而数组存储的数据类型为int,也就是说a是一个int类型的地址(即a的关联类型为int)。而一级指针变量p的定义则是存储一个int类型的地址,因此p=a是完全没问题的(即把一个int类型地址赋值给一个存储int类型地址的指针变量)。这里,我们就用到了上面提到的关键,数组的变量名是数组中第一个数据的地址以及我所提到的核心,指针的关联类型。
问题2:如图02所示,为什么a+1就是数组的第二个数据呢?
要想比较准确的理解这个问题,我们就要理解好指针的关联类型以及指针运算。首先,我们在上面已经讲过,数组变量名a是数组中第一个数据的地址,很明显,a的关联类型就是int。在C++中,指针是按与指针关联的数据类型的字节数进行加减运算的,a+1意味a移动一个int类型的字节数。所以a+1的含义就是移动到下一个int数据。
对于这个问题,我们需要延伸一下,大家觉得这段代码是否正确呢?
1 int a[3] = {1, 2, 3};
2 int *p;
3 p = &a;
问题的答案...还是先说吧,是错的。对于取址运算符&,我们要理解的一个关键点是,取址运算符&返回变量的地址,也就是说取址运算&返回的是一个指针,而这个指针的关联类型很明显就是这个变量的数据类型。在这个例子中,变量a的数据类型是长度为3的整数数组,即int[3],所以&a返回的是一个关联类型为int[3]的指针。而p存储的是一个关联类型为int的指针变量,因此上述代码是错误的,正确的代码如下:
1 int a[3] = {1, 2, 3};
2 int (*p)[3];
3 p = &a;
综合上面所说的,我们得出以下几点核心观点:
-
数组的变量名既代表一个变量,也代表一个指针
-
每个指针都有一个关联变量
-
取址运算符&返回的是一个关联类型为该变量数据类型的指针
-
指针只能赋值给用于存储相同关联类型的指针变量
尊重别人的知识成果,转载/引用请注明出处~
By 淼
2015/3/12