文章目录
- 一、数组
- 二、[]使用原理
- 三、指针数组与数组指针
- 指针数组
- 数组指针
- 四、数组名、*数组名与&数组名的区别
- 一维数组
- 二维数组
- 空间移动计算
- 总结
一、数组
数组(英文 array)就是一组同类型变量的集合。它具有三个特性:长度固定、连续存储,有序编号每个成员,编号最小为 0,最大为长度减 1。
变量是不能作为数组长度的。只能用整型常量才可以。
数组不完全初始化。即仅给出部分成员的值,其它未赋值的默认为 0。
数组名在一般情况下是指向数组中第一个对象的指针常量,也就代表其不能被修改。
这个一般,会在sizeof和&中会被破坏。
- 当数组名单独放在sizeof内部的时候会代表整个数组。
- 对数组名使用&取地址所产生的值的类型是一个指向整个数组的指针,而不是一个指向指针常量的指针
数组名+整数得到的是数组内某成员的地址。所以数组名+整数是数组成员间的移动。
数组名用&取地址运算后,得到的是整个数组类型(即 5 个 int 类型变量空间)的指针,所以再加 1 是整个数组类型的空间偏移。(后面会仔细谈这个问题)
一维数组的数组名是一个代表数组首元素的地址,一维数组名加整数是数组成员间的偏移,即指向某数组成员。
二、[]使用原理
[ ]不仅仅是数组的标志,其本身是一个运算符;优先级和( )一样,都是最高的优先级。其使用格式为:参照地址[偏移量]。
参照地址[偏移量] 等价于 * (参照地址+偏移量)。也就是 arr[1]背后的计算过程是* (arr+1)。也就是 arr 这个数组名代表的是数组首元素的地址,arr+1 代表从第 0 个成员地址开始偏移指向下标 1 成员的地址。* (arr+1)就代表下标 1 成员的空间。我们也可以理解成 arr[N]相当于* (arr+N)的快捷方式。
三、指针数组与数组指针
指针数组
int* p[4]是一个指针数组
int代表的是个 int 型指针,[4]是该类型变量数量的扩展,所以 int [4] 整体代表的是一个数组类型,即拥有 4 个成员的指针类型的数组(简称:指针数组)。
数组指针
int(* )[4]是一个数组指针
数组指针是对指针可以指向更大内存空间的扩展类型。
把数组名的位置用“(* )”代替,即 int(* )[4],其就可以是一个扩展空间了的指针类型,代表的是指向 4 个 int 的指针类型
四、数组名、*数组名与&数组名的区别
一维数组
数组名一般是首个成员的地址,所以数组名+整数是数组成员间的移动。
*数组名代表取数组的首元素,A = &A[0] * A = A[0] = * &A[0]
数组名用&取地址运算后,得到的是整个数组类型(即 5 个 int 类型变量空间)的指针,所以再加 1 是整个数组类型的空间偏移。
切记:
- 当数组名单独放在sizeof内部的时候会代表整个数组。
- 对数组名使用&取地址所产生的值的类型是一个指向整个数组的指针,而不是一个指向指针常量的指针。
这是两种特殊情况
#include <iostream>
using namespace std;
int main()
{
int nums[4] = { 0 };
cout << nums << endl;
cout << nums + 1 << endl;
cout << *nums << endl;
cout << *nums + 1 << endl;
cout << &nums << endl;
cout << &nums + 1 << endl;
}
解释:&num的类型是指向整个数组的指针,而num是指向num[0]的指针,虽然在数值上相同(结果的第1行和第5行),但是在类型上不同。所以+1所得到的值也不同。
一个是地址+4,这是因为移动了一个 int 类型的空间大小。
而另一个是+16,这是因为移动了一个数组(我这里数组大小是4),移动了4*4=16的空间大小。
二维数组
来看看二维数组,
其实+1中这个1代表的是当前数组最高维度的空间大小。
二维数组名字+1代表着偏移最高维度的大小。
#include <iostream>
using namespace std;
int main()
{
int nums[4][3] = { 0 };
cout << nums << endl;
cout << nums + 1 << endl;
cout << *nums << endl;
cout << *nums + 1 << endl;
cout << **nums << endl;
cout << **nums + 1 << endl;
cout << &nums << endl;
cout << &nums + 1 << endl;
}
第一个+1代表着偏移最高维度的大小,即行的偏移,也就是+12
第二个+1代表着第一个元素的偏移,+4
第三个是元素值+1
第四个是移动了整个数组,即344=48
空间移动计算
建议:画个图!最好画个图!
要不然很容易乱
例:
//以下代码的执行结果是().
int main(){
int a[5][2] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int* p = a;
int (*p2)[2] = &a[1];
++p;
++p2;
printf("%d\n", *p);
printf("%d\n", **p2);
printf("%d\n", p2[1][2]);
return 0;
}
正确答案为:1,4,8
解释:
注意p2是一个含有两位的数组指针,每次移动是本身的大小(2)
例:
在头文件及上下文均正常的情况下,下列代码的运行结果是
int a[] = {1, 2, 3, 4};
int *b = a;
*b += 2;
*(b + 2) = 2;
b++;
printf("%d,%d\n", *b, *(b + 2));
答案为2,4
总结
这就是我大概的理解,说实话数组这里小坑还是不少的,做题时候建议画图。