指针和普通变量的一样,本质没有区别,指针的本质就是变量。指针全名就是指针变量。
1.什么是指针?
#include<stdio.h> int main(void) { int a = 0; float b = 3.14; char c = 'a'; }
分析:
变量 a 的数据类型是int,a存放整形数据
变量 b 的数据类型是float,b存放浮点数
变量 c 的数据类型是char,c存放字符型
思考1:我们发现一个变量的存放什么样的数据取决于他的数据类型,对于一个变量,我们想让它是什么类型就定义成什么类型,我要整型变量b,int b这样就能得到了。思考:我要指针类型的p,怎么办?肯定得有一个”指针类型“吧?
int * p;//定义一个指针p
这样我们就得到一个指针p,类型是int*,其实是指针p指向int的地址。指针本身没有类型。就好比一块地本身不是商场也不是居住房,就看我们怎么规划这块土地。
思考2:整型变量存放整形数据,浮点类型数据存放浮点数据,那指针存放什么数据?
指针存放的都是地址,指针的类型只代表指针存放什么类型数据的地址。
int * p1 //指针p1存放int类型数据的地址
float *p2 //指针p2存放float类型数据的地址
char *p3 //指针p3存放char类型数据的地址由此来看指针只能存放地址。关键取决于存放什么类型数据的地址
int a = 10; //int类型的a
int pa = &a; //所以要存放a的地址,指针pa只能是int类型的
思考3:如何让定义一个指针,指向浮点数?(所谓指向就是保存被指向的变量的地址)
float b = 3.14; //定义一个浮点数b
float *pb =&b; //定义一个指针指向b
2.为什么使用指针
(1)为了间接访问,cpu通过寄存器间接访问一个物理地址,cpu直接访问地址叫做直接访问。
(2)需要注意的是:指针是必然出现的。因为cpu需要间接访问地址。
3.指针如何使用?
(1)三部曲:定义,赋值,解引用。这三步缺一不可,
#include<stdio.h> int main(void) { int a = 10; //第一步:定义一个int数据 int *pa = &a; //第二步:定义一个指针并赋值 *pa = 20; //第三步:解引用 printf("*pa = %d",*pa); //*pa = 20 printf("a = %d",a); //a = 20 }
思考4:为什么a也变成了20?
当第二步中,把a的地址赋值给指针pa以后,相当于给了指针pa一个可以进入a家里的钥匙,可以随意进出,一旦把钥匙给了pa,当a回家一看,完了,家里被盗了。。
(2)指针和地址
pa 存放的是a的地址
*pa 就等价于寻访pa存放的地址所对应的变量。也就是pa 是等于a的
& 表示取出一个变量的地址
* 表示访问一个地址存放的变量是谁
(3)来看看 * 用在不同地方的区别
int * p = &a; //定义指针时,*表示该变量是一个指针类型
* p = 250; //解引用时,*表示访问该地址的变量
(4)再来看一个细节
int * p1,p2;
p1、p2分别是什么类型?先假装思考一下~~~~
p1是int*,而p2是int类型,所以当我们需要连续定义两个指针变量时需要这么定义
int * p1,*p2;
(5)指针定义并初始化,与指针先定义后赋值的区别
(1)指针的初始化就是给它赋初值,
(2)指针定义初始化: int a = 1; int *p=&a;
(3)再定义之后赋值:int a = 1; int *p; p = &a;
(6)左值和右值
我们来看一下下面这句代码
int a = 10,b = 20;
a = b;
有没有想过执行完这一句编译器做了什么?
一步一步分析:
第一步:编译器看到要定义变量,先找类型,找到是int类型
第二步:编译器在内存中分配一个int类型大小的字节地址(0x12345678),并标记和变量a绑定。再找到一个地址0x12345679和b绑定
第三步:给a赋值,a = 10:编译器自动找到变量a对应的地址(0x12345678),把10写入地址0x12345678
编译器自动找到变量b对应的地址(0x12345679),把20写入地址0x12345679第四步:编译器一看要要执行a = b;于是找到变量b对应的地址0x12345679里面的值(20)写入变量a对应的地址0x12345678
第五步:思考左值和右值的区别:a = b; 把b的值写入a对应的地址,
总节:
左值和右值时一大重点,后面我们还会再来研究的,这里只开一个头。