最近在读《C primer plus》,后面的指针和多维数组感觉很绕,有必要写博文理清一下思路。如有不对,恳请指正。
指针数组,还是向数组的指针?
由于方括号[]的优先级要高于*号,所以
int *m[5]表示一个由五个指针构成的数组。
而
(int *)m[5]表示一个指针,一个指向有五个元素的数组的指针。
update:2018.11.15发现直接下结论有点草率,写了如下代码进行试验
#include <cstdio>
int main(){
//先开辟一片静态的空间,随便赋值i * j
int a[10][10];
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
a[i][j] = i * j;
}
}
int (*b)[10] = a;
//方括号的优先级大于*,所以*需要添加括号
//先算*代表b是一个指针,指针类型是int (*)[10],即指针类型是10个元素的数组
//定义指针类型的重要性在于,每次指针加i,代表着指针偏移i*(指针类型大小)的空间
//赋值操作需要在指针类型相同的情况下进行,因为a和b都是int (*)[10]所以可以赋值
printf("output b:\n");
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
//先运算里层的*(b + i),即从b开始,偏移i个int [10],然后*号取值
//即b + i所指向的地址中存放的地址值
//然后再偏移j个int,再*号取值就是a[i][j]的值
//简单来说就是先偏移i * 10 个int,再偏移j个int
printf("%d ", *(*(b + i) + j));
}
printf("\n");
}
int *c[10];
//表示c是一个数组,里面存着int*指针的数组
for(int i = 0; i < 10; i++){
//c是一个存着数组的指针,所以c[i]就是一个指针
//让c每个元素等于由a数组中的元素
//因为a中的每个元素是一个int [10]的数组,也是int *类型的指针
//两个同样类型的指针赋值是合法操作
c[i] = a[i];
}
printf("output c:\n");
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
// *(c + i)即c数组中的第i个元素,是个int *指针
//int *指针偏移j个int,即c[i][j],也是a[i][j]
printf("%d ", *(*(c + i) + j));
}
printf("\n");
}
}
7 指针和多维数组
int a[4][2]
指针的值和它首个元素的地址是一样的,所以a的值,也就是a[0]的地址。
a[0]是一个指向int类型的指针,所以a[0]的值,就是a[0][0]的地址。
#include<stdio.h>
int main()
{
int a[4][2];
printf("value of a:%p\n",a);
printf("address of a[0]:%p\n",&a[0]);
printf("value of a[0]:%p\n",a[0]);
printf("address of a[0][0]:%p\n",&a[0][0]);
return 0;
}
这段代码的运行结果可以看到,a的值和a[0]的地址是一样的,a[0]的值和a[0][0]的地址也是一样的,就证明上面两句话。
指针+1
a指向的对象是a[0],而a[0]是一个指向一个两个int数的数组的地址,int的字节长是4,a[0]的字节长是8
但是a[0]指向的是一个int数的数组,所以a[0]的字节长是4。
所以,a增加1会导致他的值增加8.而a[0]加1会导致它的值增加4。a+1和a[0]+1的结果是不一样的
10.7.1 指向多维数组的指针
int (*pz)[2]
表示pz是一个指向一个包含两个int值的数组
而如果不加圆括号,因为[]的优先级比*的优先级高,所以'int *pz[2]'则表示的是,pz是个数组,是个包含两个int指针的数组