C/C++ 的指针
指针变量也是变量,很多时候可以用普通变量的思维去思考和使用,与普通变量不同的是,普通变量装的一般的数据类型,指针变量装的是其它变量的指针(地址)
0. 指针数组
指针数组也就是指针的数组,它和普通数组的区别就是普通数组里面装的是常见的数据元素,指针数组里面装的是指针元素
int a = 1, b = 2, c = 3;
int* p[3] = {&a, &b, &c}; // p[1] == &b; p[1][0] == b;
下标运算符 “[ ]” 不是指针特有的,只要符合下标运算符的操作规则,就可以使用
下标运算符” [ ] “用法
下标运算符执行的操作是:*(地址+[偏移量])
由下标运算符的操作方法可以看出,下标运算不是数组特有的,例如:
int a[3] = {1, 2, 3};
int *p = a;
p[1] 相当于 (p+1) 也就是 a[1],更”奇葩”的是它还相当于 1[p],根据下标运算符的操作 1[p] 相当于 (1+p),这里的 “+1” 操作跨过的是 *p 类型的数据长度(这里是 4Byte ),也可以说步长是 4Byte
1. 数组指针
数组指针也称行指针,步长是整个数组的长度
int a[3] = {1, 2, 3};
int (*p)[3] = &a;
// 也就是表示:
p == &a;
*p == a;
(*p)[1] == a[1];
int b[2][3];
int (*q)[2][3] = &a;
注意
-
数组指针与其它数据类型的变量一样,可以用指针访问这个数组,但是必须保证元素类型、维度、以及每个维度上的元素数一致,一个数组指针一次只能表示一个数组
-
上面代码中 p 的步长是 3 个 int 的长度,即 12Byte;q 的步长是 2*3 个 int 的长度,即 24Byte
2. 数组名和指针的比较
区别
-
同类型指针变量可以相互赋值,数组不可以,只能一个一个元素赋值或拷贝
-
数组在内存中是连续存放的,开辟一块连续的内存空间,数组是根据数组的下标进行访问的,多维数组在内存中是按照一维数组存储的,只是在逻辑上是多维的
-
指针很灵活,可以指向任意的数据类型,指针的类型说明它所指向地址空间的内存中存放的数据的类型
-
数组在内存中所占存储空间 sizeof(数组名),数组的大小 sizeof(数组名)/sizeof(数据类型)
-
指针存放的是某一数据类型的内存地址,在 32bit 系统中,地址的寻址空间是 32bit 的,因此 sizeof(指针) 都是 4Byte,在 64bit 系统中,地址的寻址空间是 64bit 的,因此 sizeof(指针)都是 8Byte
-
数组名指向的地址是不可变的,指向的始终是数组的起始地址;指针变量顾名思义是变量,指向的地址一般是可变的(顶层 const 类型指针指向的地址是不可变的)
联系
数组传参时,会退化为指针
void fun (int a[]);
void fun (int* a);
// 这两个声明的效果是一样的,编译的过程中 void fun (int a[]); 中的数组会转化为指针形式