二、指针的解引用
关于指针的解引用,先看一道例题
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n = 0x11223344;
char*pc = (char*)&n;
int*pi = &n;
*pc = 0x55;
*pi = 0;
system("pause");
return0;
}
从这道例题中能挖掘的知识点--->
(1)数据的存储方式(大小端)
(2)指针变量的类型有什么作用?能决定什么?
(3)解引用取出的是什么?,和类型有什么样的关系?
接下来我们可以通过调试查看内存的方式探索一下
通过调用内存可以看出,在这个平台下,数据的存储是:低位放在了低地址处。这里牵扯到一个大小端的问题。简单来说,小端存储是指:数据的低位存放在低地址。大端存储是:数据的高位存放在高地址。
指针变量类型本身其实并没有什么,拿本题来说,一个int型的变量n,我们分别定义了char类型的指针变量pc和int类型的指针变量pi来存储n的地址,printf("%p\n",pc)与printf("%p\n,"pi)打印结果相同。也说明了指针变量的类型并不会影响它存放地址,原因是:指针变量在存储地址时,实际上是只保存数组首元素最低位那个字节的地址。
但是通过对指针解引用修改n中的数据,我们发现,定义不同类型的指针变量,在解引用时取出的字节数不同,上图为例,char类型的指针变量pc只修改了n的一个字节。由此可以证明:指针变量类型在进行“解引用”操作时会有影响,它决定“解引用”时能取出多少字节的数据。
这里再举一个例子证明一下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch = 'w';
int*pc = &ch;//定义一个int类型的指针变量来保存ch的地址
char*pp = &ch;//定义一个char类型的指针变量来保存ch的地址
*pc = 'm';
printf("%c\n", *pc);
//输出pc和pi的地址
printf("pc=%p,pp=%p\n", pc,pp);
system("pause");
return 0;
}
运行结果:
监视查看:
可以看到,无论是用int类型的指针变量pc还是char类型的指针变量pp保存ch的地址,最终输出结果都是一样的,也就证明了指针变量的类型不会影响到它所保存的地址,因为指针变量在保存地址时,其实保存的都是最低字节的那一个地址。
三、指针+-整数
还是用一个例子来剖析
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10] = { 0 };//元素是int类型
int*first = &a[3];//定义一个int类型的指针变量
//first++;
int*second = &a[9];//定义一个int类型的指针变量
printf("%d", second - first);
system("pause");
return 0;
}
具体图解-->
可以看到,当指针变量的类型与元素的类型相同时,指针相减的结果正好是元素个数。
如果指针变量的类型与元素类型不一致呢?
int a[10] = { 0 };//元素是int类型
short*first = &a[3];//定义short类型的指针变量
first++;
short*second = &a[9];//定义short类型的指针变量
printf("%d\n", second - first);
printf("%p\n", first);
printf("%p\n", second);
printf("%p\n", second - first);
以上两种方式的内存布局即指针具体内容如下:
左图(元素类型与定义的指针变量类型一致),右图(元素类型与定义的指针变量类型不一致),对比如下-->
调出窗口查看验证结果
所以,下面这段代码的运行结果是12.
int a[10] = { 0 };
short*first = &a[3];
short*second = &a[9];
printf("%d\n", second - first);
总结:两个指针相减代表两个指针之间所经历的元素个数
经历的元素个数又由指针变量的类型决定。这里的元素个数不是狭隘的定义数组时我们所说的“元素个数”,而是
元素个数=数据中两个地址的距离(单位:字节)除以 存储数据地址所定义的指针变量的类型。这也就解释了上面的例题,为什么一个输出结果是6,一个是12。
6=24/4 12=24/2