指针的使用 指针运算符&和* 运算符*的使用举例 运算符&的使用举例 小结

文章目录

个人认为,操作指针需要清楚两件事情。一、明白在操作的内存地址;二、清楚当前指针移动的步调会有多大,在这一点上就需要与前面的知识结合起来,需要非常清楚指针所指向的数据类型在内存中的大小。

指针运算符&和*

&是取地址运算符,会返回变量所匹配的内存空间的地址。比如说a是一个变量,绑定着一块存储着数据的内存空间。而&a就会把a所绑定的那块数据内存空间的首地址返回来。要是不理会内存管理的知识的话,可以简单的说就是返回a的地址。

*是间接运算符,它的作用就是拿到指针所指向的那块内存空间里面的东西。

个人认为,可以把’&’和’‘两个运算符认为是一组运算符,说白了就是&负责取地址,而负责拿到地址里面的东西。

运算符*的使用举例

例一:读取与修改

1
2
3
4
5
6
int a = 10;
int *p = &a;
cout << *p << endl;
*p = 500;
cout << a << endl;
cout << *p << endl;

p拿到a的地址后,通过*p拿到a所绑定的内存空间里面的数值10,然后还可以直接对该内存空间进行修改,将数值改为500.

例二:注意指针移动的步调

land:c
1
2
3
4
5
6
7
8
9
char a[20] = "You are a student";
char *ptr1 = a;
int *ptr2 = (int *)a;
ptr1++;
ptr2++;
cout << *ptr1 << endl;
cout << *ptr2 << endl;
ptr2 += 5;

指针ptr1的类型是char,指针ptr2的类型是int,ptr1指向的是char型数据,ptr2指向的是int型数据。一个char在内存中占一个byte,一个int在内存中占4个byte,所以ptr1移动的步调是一个byte一个byte的移动,ptr2移动的步调是4个byte4个byte的移动。当然,前辈早已经为我们总结了公式——指针移动的内存单元=指针移动的数值*sizeof(指针所指向的数据类型)。
其实最重要还是要理解背后一些实质性的东西。那么指令ptr2 += 5;执行后会有怎么样结果呢?

例三:二级指针的误区

1
2
3
4
5
6
char a[20] = "You are a student";
char *p = a;
char **ptr = &p;
cout << **ptr << endl;
ptr++;
cout << **ptr << endl;

程序输出的结果会是什么?Y和o,还是Y和a?
指针p指向字符串的内存空间,类型为char,移动步调为一个byte。而指针ptr指向指针p所在的内存空间,类型为char*,其移动步调应该为4个byte。所以当执行ptr++的时候,的确是移动了4个byte,但是移动的内存空间是存储着指针p的内存空间,而不是存储着字符串的内存空间,这是两块不同的内存空间哟!要是无法抽象理解的话,可以看看前面指针的内存布局。在VS2013中,这会被提示是一个非法操作,因为你不知道存储着p的那块内存空间是什么东西,或者什么东西也不是!

运算符&的使用举例

例一:取地址加运算的陷阱

1
2
3
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a + 1);
cout << *(a+1) << *(ptr-1) <<endl;

对于这种陷阱,个人觉得,要是我们对程序稍微修改一下,是不是会更清楚呢?

1
2
3
4
5
6
7
int a[5] = {1,2,3,4,5};
//做如下修改的话
//int *ptr = (int *)(&a + 1);
int (*ptrTemp)[5] = &a; //定义了一个指向数组长度为5的指针。
ptrTemp++;
int *ptr = (int *) ptrTemp;
cout << *(a+1) << " " << *(ptr-1) <<endl;

这样是不是会更加清晰一点?指针ptrTemp指向的数据类型为int()[5],移动的步调为sizeof(int()[5]) = 5*4 = 20个byte。也就是说,每次会移动一个长度为5的整型数组的大小。而ptr指向的数据类型为int,移动的单位为sizeof(int)=4个byte。所以当赋值之后,ptr实际上指向的是a[5]后面的一个内存单元,所以当ptr-1的时候,退后4个byte的长度,正好指着a[5]。

可能要有人觉得,指针不就是数组吗?至少我本人就犯了这个错误犯了很长时间。数组与指针,相似而不相同,往后再慢慢介绍!

小结

正如前面所说,对指针的操作,其实就三件事情。忽略运算符的话,就是两件事情。一、明白指针操作的是内存地址,清楚当前操作的内存空间。二、清楚当前指针所指向的数据类型,理解指针移动的单位,一个类型为T的指针的移动,以sizeof(T)为移动单位。理解好这两点就可以了,我个人觉得。