指针的本质
取地址操作符:&
取值操作符:*
![](https://img-blog.csdnimg.cn/img_convert/e09d5066d4f9383fc1bf6d12cbee5251.png)
指针的传递
我们将变量i的地址传递给change函数时,实际效果是j=&i,依然是值传递,只是这时我们的j是一个指针变量,内部存储的是变量i的地址Ox0015ff0c,所以通过*j就间接访问到了与变量i相同的区域,通过*j=5就实现了对变量i的值的改变.我们依然可以看到变量j自身的地址是0x0015fe38,它与变量i的地址依然不相等
![](https://img-blog.csdnimg.cn/img_convert/68b22f26ef1b1fe30cbddd67786b8cc8.png)
指针的偏移
*p++由于*和++的优先级相等,所以会先进行取值,再进行偏移
![](https://img-blog.csdnimg.cn/img_convert/448601023005202914b7d34ecc0cdb97.png)
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/0c3b4e1be50f5ac821a59efec545d52a.png)
为什么第一次输出的是j=2,*p=7呢?首先,前面讲过当遇到后增操作符时,就要分两步来看.第一步是暂时忽略++操作,即 j=*p,因为p指向数组的第一个元素,所以j=2。那么第二步是对p进行++操作,还是对*p整体也就是数组第一个元素的值进行++操作呢?这里实际上是对p进行++操作,因为*操作符和++操作符的优先级相同,只有比++优先级高的操作符(参阅附录B)才会当成一个整体,目前我们用过的比++操作符优先级高的只有()和[]两个操作符.
第二次输出为什么是j=7,*p=8 呢?首先,p指向的是元素a[1],对于 j=p[0]++,忽略++操作,也就是j=p[0],所以j=7.接着是对p进行++操作还是对p[0]进行++操作呢?显然,是对p[0]进行++操作,所以* p等于8.
动态申请空间
在学习C语言的数组后都会觉得数组长度固定很不方便,其实C语言的数组长度固定是因为其定义的整型、浮点型、字符型变量、数组变量都在栈空间中,而栈空间的大小在编译时是确定的.如果使用的空间大小不确定,那么就要使用堆空间。使用malloc函数可以动态申请内存空间,申请完之后必须进行释放。(类似图书馆)
![](https://img-blog.csdnimg.cn/img_convert/77d43f61f6d135dab7d03c9697ffed2e.png)
其中,i代表要申请的空间大小,单位是字节。
首先我们来看malloc函数。在执行#include <stdlib.h>void *malloc(size_t size);时,需
要给malloc传递的参数是一个整型变量,因为这里的size_t即为int;返回值为void*类型的指针, void*类型的指针只能用来存储一个地址而不能进行偏移
因为malloc并不知道我们申请的空间用来存放什么类型的数据,所以确定要用来存储什么类型的数据后,都会将void*强制转换为对应的类型。在例5.2.5中我们用来存储字符,所以将其强制转换为char*类型。
定义的整型变量i、指针变量p均在main函数的栈空间中,通过 malloc申请的空间会返回一个堆空间的首地址,我们把首地址存入变量p。知道了首地址,就可以通过strcpy函数往对应的空间存储字符数据
静态--栈 效率高 会随着函数的进行自动释放
动态--堆 效率低
![](https://img-blog.csdnimg.cn/img_convert/e336df235115f303c5f2318b08dab510.png)
free(p)之后,p的值没有变,仍然指向那段内存空间,此时为野指针(指向不属于自己的内存),需要将p=null
![](https://img-blog.csdnimg.cn/img_convert/d315cd46037aa8e16bfe56ccc3af1c0d.png)
两种赋值方式,但第一种不可以对常量区数据进行修改 p[0]='H'这个代码是非法的
![](https://img-blog.csdnimg.cn/img_convert/f2dc86084d26b573433c56337bbc0d15.png)
但是可以将字符串world的地址赋给p,不能将字符串赋给c