再看C数组与指针
下面这段代码是合法的:
srand(time(0));int arr[10] = {0};for (int i = 0; i < 10; ++i) {arr[i] = rand() % 100;}for (int i = 0; i < 10; ++i) {cout << i[arr] << endl;}
你能明白是为什么嘛?如果不明白,那么这篇文章将会教会你。
指针与数组
这两个概念其实密不可分。如果不能彻底理解其中一方,就会导致也无法理解另一方。
数组
C语言中的指针有下面两点需要注意:
- C语言中只有一维数组,而且数组的大小必须在编译期就被确定。但C语言中的元素可以是任意对象。
- 对于一个数组,我们只能做两件事:确定数组大小、获得该数组下标为0的指针。其他有关数组的操作,都是在上面的指针基础上运行的。因此我们完全可以依赖指针行为来定义数组的下标行为。
指针
指针的一些细节如下:
- 任何指针都是指向某种类型的变量
- 如果指针指向的是数组中的一个元素,那么只需要给指针加1,就能够得到指向该数组中下一个元素的指针。同样的,如果我们给这个指针减1,得到的就是指向该数组中前一个元素的指针。
数组与指针的联系
上面的特性暗示了下面的事实:
给指针加上一个整数,与给该指针的二进制表示加上同样的整数,这两者的含义截然不同。
如果指针p指向一个整数,那么p+1指向的是计算机内存中的下一个整数。
如果两个指针指向的是同一个数组中的元素,我们可以把这两个指针相减:
int *q = p + i;
那么我们可以通过 q - p
来得到 i
的值。如果 p
与 q
指向的不是同一个数组中的元素,即使他们所指向的地址在内存中的位置正好间隔一个数组元素的整数倍,所得到的结果仍然无法保证。
数组与指针的转换
数组名代表这个数组第一个元素的地址,
如果我们这样做:
int a[3];
int *p = a; // 将数组第一个元素的地址赋值给指针p
此时p指向数组的第一个元素,因此解引用后就可以访问第一个值:
cout << *p << endl; // 输出a[0]的值
如果想要通过这个指针来访问 a[1]
呢?
只需要在p上向后加1就可以了:
cout << *(p + 1) << endl; // 输出a[1]
可以发现:
数组与指针的相互的解释关系是这样的:
a[1] = *(a + 1); // 这里假定a是一个数组首地址
既然如此是不是也可以这样做呢?
1[a] = *(1 + a);
没错!你真的可以这样做,这就是为什么我们开头所给出的那个例子是合法的原因。
多维数组地址转换
将数组中的元素改为数组地址,就得到了一个二维数组:
二维数组的声明方式是这样的:
int a[100][100];
用指针先表示其中的一维是这样的:
假设我们表示 a[50][50]
*(a[50] + 50);
再去掉一维:
*(*(a + 50) + 50);
:wq 拜拜~~~~