??“同学们,前两天我们学习了变量和内存,并且我们都知道了变量是存储在内存中的。但你们有没有想过,CPU是如何识别和操作我们内存中的变量的呢?我给你们举个例子,你们就明白了。假如我们现在在家订外卖,是不是要先下单然后填写地址“xx小区xx号楼xx单元xx门牌号”,然后经过漫长的等待,外卖员才会把你的晚餐送到你的家门口。其实,计算机也是类似的,我们把内存比作你家的小区,把变量比作你的家,那么前面说的一串‘xx号楼xx单元xx门牌号’地址就可以看做是变量存储在内存中的地址。然后CPU就好比外卖员能根据你提供的地址准确的找到你家一样,CPU也能根据变量的地址准确的找到内存中的变量并获取变量里面的数据。” ??“那我们能不能看到变量存储在内存中的地址呢?”小韩好奇的问道。 ??“当然可以,我们不但能知道变量在内存中的存储地址还可以对变量的地址进行操作。在C语言中就有专门的一种变量可以对内存中的地址进行操作。这就是我们今天要讲的指针变量。” ??“变量我能理解,那指针是什么呢?”坐在前排的小美问道。 ??小刘解释道:“指针就是变量存储在内存中的地址,只不过为了我们能更好的理解起了个形象的名字,就好像一根针指向某个地方的意思。接下来我用代码给大家演示一下:[code_1]”
#include<stdio.h>
int main()
{
int a = 100;
char str[20] = "123456";
printf("a的地址 = %#X\nstr的地址 = %#X\n",&a,str);
return 0;
}
输出
??“上面的代码中我们定义了两个变量,一个整数型变量a,一个字符型变量str,然后我们输出两个变量的地址,%#X表示输出的是带前缀0X的十六进制数,输出a变量的地址要加&(取地址符),数组str就直接代表了数组的首地址,所以不用加&。下面我们用指针变量(下面都简称指针)来输出a和str的地址:[code_2]”
#include<stdio.h>
int main()
{
int a = 100;
char str[20] = "123456";
int *p1;
char *p2;
p1 = &a;
p2 = str;
printf("a的地址 = %#X ,str的地址 = %#X\n",&a,str);
printf("p1 = %#X ,p2 = %#X\n",p1,p2);
return 0;
}
输出
??“上面的程序中,因为指针变量也是变量,所以可以进行定义和赋值操作。我们在定义指针变量的时候,要在变量名前加*,表示这是一个指针变量。在赋值的时候,指针变量的数据类型可以理解为对应数据类型的地址,所以在给p1赋值时,a的前面加&,说明我们把a变量的地址赋值给了指针变量p1;而对p2赋值时不加,是因为str本身就表示数组首元素的地址。” ??“我们在来分析一下输出,第一个输出没有变,输出的是a和str的地址;第二个输出我们直接输出的是p1和p2的值,而p1和p2恰好就是a和str的地址,所以两个代码输出的结果是一模一样的。” ??这时机灵的小韩问道:“指针也是一个变量,那指针按理来说也是有地址的吧。” ??小刘回答:“这个问题问的好。没错,指针作为变量也是有自身的地址的,指针变量的值是地址,且指针自身也有自己的地址,这点大家一定要注意区分,不要搞混了。我们来看看指针自身的地址。[code_3]”
#include<stdio.h>
int main()
{
int a = 100;
char str[20] = "123456";
int *p1;
char *p2;
p1 = &a;
p2 = str;
printf("a的地址 = %#X ,str的地址 = %#X\n",&a,str);
printf("p1 = %#X ,p2 = %#X\n",p1,p2);
printf("p1的地址 = %#X ,p2的地址 = %#X\n",&p1,&p2);
return 0;
}
输出
??“我们结合之前的内存分区图来更加直观的理解一下:”
黑板
??“上图中,我们只有一个main函数并且全都是局部变量,只用到内存中的栈区即可。其中红色表示指针变量,蓝色表示一普通变量,p1的值是a的地址,p2的值是str的地址。值与自身地址并不相同。”
??“除了表示变量地址,指针变量还有很多其他的骚操作,下面我们通过代码来演示一下:”
??“显示所指地址的值:[code_4]”
#include<stdio.h>
int main()
{
int a = 100;
int *p1 = &a;
printf("a = %d , *p1 = %d",a,*p1);
return 0;
}
输出
??“通过指针变量修改所指地址的值:[code_5]”
#include<stdio.h>
int main()
{
int a = 100;
int *p1 = &a;
*p1 = 200;
printf("a = %d , *p1 = %d",a,*p1);
return 0;
}
??“这里需要提一点,定义时的 * 和赋值时的 * 是两个意思:第一个表示:这是一个指针变量;第二个表示:获取指针指向地址处的数据;第三个指针需要注意的是:在使用指针所指向的值的时候要加 *,如: *p1 = 200; 在对指针变量本身赋值的时候,不加 * 如:p = &a; ”
输出
??“通过指针交换两个变量的值:[code_6]”
#include<stdio.h>
int main()
{
int a,b,temp;
int *p1,*p2;
a = 100;
b=200;
printf("交换前:a=%d,b=%d\n",a,b);
p1=&a;
p2=&b;
temp = *p1;
*p1 = *p2;
*p2 = temp;
printf("交换后:a=%d,b=%d\n",a,b);
return 0;
}
输出
初始: 交换: ??temp = *p1
??*p1 = *p2 ??*p2 = temp ??“刷新指针。” ??“今天指针的内容就讲这么多,大家课下也要多多练习,勤打代码,提高自己的编程能力。下课。”
|