1.指针的自增自减
我们前面说过,指针的本质就是地址。我们可以通过操作指针操作其对应的变量,那么对指针进行加减操作就很重要了,当我们对指针进行自增自减时,有什么样的规则呢?上代码:
我们定义了一个整形指针p指向整形数组a,定义一个变量j用来接收对p进行操作的内容。
很明显,a[0]=2.在c语言中,++运算符和运算符是同一优先级的,在这种情况下,我们按从右到左的顺序进行运算,那么j=p++这句采用了后++的代码,代表的就是先将p这个整体赋值给j,而p是指向数组首地址,故j=2。而后由于++和优先级相同且++在右,故优先运算++,即先运算p++,再将这个偏移了的指针进行取值运算,所以此时p指向数组的第二位,所以*p=7.
那如果我们再写一句代码j=p[0]++,值又会如何改变呢:
a[0]维持不变,还是2。j=p[0]++我们需要拆解成两部分,首先脱掉这个自增,j=p[0];
而此时这个p指向的是数组第二个位置,所以j=7; 接下来很明显[]是优先级大于++的,所以我们应该对p[0]整体进行++,因此数组第二个位置从7变成了8,也就是说*p=8.
因此我们可以得出结论,归纳总结:
指针的自增自减问题,先拆自增自减符,再看谁优先级高
2.malloc动态数组
有时候我们需要输入的数组元素个数并不固定,我们输入个数后,需要输入对应个数的数据,但很明显,这样太麻烦了。所以我们在想,可不可以我们输入个数后,申请一段相应大小的空间用来接收数据呢?这就需要用到我们的malloc函数:
malloc函数需要传入需要申请的内存大小,以字节为单位,返回一个空指针,因此我们需要申请完空间后进行强制类型转换,然后用一个相应类型的指针进行接收。值得注意的是,每种数据类型所占有的字节数并不相同,例如一个int型整形数占4个字节,而一个char型字符却占1个字节。
所以这里相当容易造成下标越界访问,例如本来我申请一个20字节的空间用来存储int型变量,一个int整形数占4个字节的大小,所以这个内存空间最多放5个整形数,所以下标最多访问到4,这就是为什么很多人使用malloc申请空间很容易出现越界访问。
3.浅淡堆栈
在我们计算机系统中有两种最为常用的数据结构,一个是栈,一个是堆。
栈是计算机系统提供的数据结构,效率比较高;
堆类似我们的图书馆,我们需要空间必须像去图书馆借书一样去申请,申请空间进行使用后,还必须”还书“,即释放这段内存空间。因此需要用到我们的malloc和free函数。这两个函数都需要我们传入指针变量,由于只是对内存的申请和释放,所以指针不能进行偏移。
下面我们来写两段代码来更好理解堆和栈的区别。我们写了两个函数,分别返回栈空间和堆空间的一段首地址,而在栈空间的地址返回会出现问题,是因为栈空间释放后,函数内的所有局部变量都会消失,而堆空间不会因为函数的执行结束而释放。