在C语言下,我们申请了一个指针*P;系统会分配一个地址给这个指针,其地址为&P。该地址下存放的是这个指针指向的地址P。这个地址下存放的是这个指针实际的值*P。至于指针的++这里有两种,分别为(P++、&P++)。正如我们上文中所说的,P是指针指向的地址,那么P++就是指针指到之前的地址的下一个地址。
(这两个图片是我从IAR编译器下截图出来的)
举个例子来说吧。比如我们定义了一个指针int* p = (int*)0x20000000。那么P++、与&p++分别是多少呢?(假设我们定义的这个指针,系统给其分配的地址为0x20000010)那么P++,值为0X20000004,而&P++值为0X20000014。
这个是不是很容易理解,那我们来点难度的,现在我们定义一个指针uint8_t* p = (uint8_t*)0x20000000.那么现在P++,与&P++又分别是多少呢?(假设我们定义的这个指针,系统给其分配的地址为0x20000010)P++的值为0x20000001,而&p++的值为0x20000014。
对比这次与上次的区别,发现只是指针的类型变了,第一次用的是int类型(4个字节),第二次用的是uint8_t类型(1个字节)。P们说过,它只是这个指针指向的地址,P++其实就是这个指针向后移一位(这一位取决于这个指针的类型)。而&P是系统给这个指针分配的地址,&P++是由系统决定的,与该指针是什么类型无关。我这里使用的是STM32,其寻址宽度为4个字节,所以指针在该系统下是4个字节的大小。而&P++就相当于P+sizeof(P);
看到这里可能还有点迷,那我们以另外一个数据类型来分析一个。
这里区分数组名与数组名取址的区别。
假设我们定义一个数组 intarr[5]={1,2,3,4,5};那么arr++,与&arr++的结果是什么?(假设系统给该数组分配的地址为0x20000000)
arr++的结果是0x20000004,&arr++的结果是0x20000014。
其实数组在定义的时候系统也会为其分配一个内存,只是数据类型的不同,决定了数组不能像指针那样有两个地址。如果非要说的话,数组也是有两个地址,只是这两个地址相同而已。一般我们会认为arr就是这个数组的首地址,那么&arr是这个首地址的地址,相当于一个二级指针。这个理解是不正确的。就像指针一样,系统给这个数组分配了一个地址,这个地址就是&arr,而该地址下存放的就是这个数组的首地址arr。这样分析的话就会发现,arr与&arr有实质上的区别。如果指针的分析看懂了,这里应该就很容易理解为什么arr++的结果是0x20000004而&arr++的结果是0x20000014。那这里我们再说一遍,arr是系统给这个数组分配的内存下存放的地址,也就是通俗所说的数组的首地址,那么arr++就是在首地址下向后移动一位(这一位取决于这个数组的类型)。而&arr是系统给这个数组分配的地址,&arr++就相当于arr+sizeof(arr)。这样一分析是不是就清楚了很多,那么如果说现在定义的数组类型为uint8_t。那么arr++的结果就是0x20000001,&arr++的结果是0x20000005。
如果这个都懂了,那么我们来看一下更难的,这次我们使用结构体。我们先定义一个结构体
Typedefstruct{Int a;int b;int c;}sa; sa st;(假设系统给该结构体分配的内存地址为0x20000000)
那么&st.a++与&st++结果分别是多少呢?
这里结构体与数组大致相同,结果也相同,这里就不做过多介绍。&st.a++结果为0x20000004,&st++的结果为0x2000000C,&st.a++相当于在结构体首地址向后移一位(这一位取决于这个结构体子元素的类型)。&st++相当于st.a+sizeof(st)。
难度MAX,这里我们定义一个结构体指针。Typedef struct{Int a;int b;int c;}sa; sa *sp = (sa*)0x20000010; (假设系统给该结构体分配的内存地址为0x20000000)
那么sp++与&sp++的结果分别是什么?
按照我们之前分析的,系统会给这个指针分配一个地址,这个地址中存放的内容是这个指针指向的地址,那么sp++是从首地址向后指一位,那这一位具体是多少呢?在普通指针中我们知道这一位的大小是有这个指针的类型决定的,而这里我们使用的是结构体指针,那这个的大小应该怎么确定呢?其实道理是一样的,要先确定这个结构体的大小,然后首地址加上这个结构体的大小就得到了最终的结果,那么sp++应该为sp+sizeof(sa),结果为0x2000001c。&sp++的结果应该是sp+sizeof(sp),结果为0x20000004。
再说struct{uint8_t a; uint8_t b; uint8_t c;}sa; sa *sp = (sa*)0x20000010;(假设系统给该结构体分配的内存地址为0x20000000)sp++的结果是0x20000013,&sp++的结果是0x20000004。