三、指针才是C的精髓
3.1、指针到底是什么?
3.1.1、指针变量和普通变量的区别
(1)首先必须非常明确:指针的实质就是个变量,它跟普通变量没有任何本质区别。指针完整的名字应该叫指针变量,简称为指针。
3.1.2、为什么需要指针?
(1)指针的出现是为了实现间接访问。在汇编中都有间接访问,其实就是CPU的寻址方式中的间接寻址。
(2)间接访问(CPU的间接寻址)是CPU设计时决定的,这个决定了汇编语言必须能够实现间接寻址,又决定了汇编之上的C语言也必须实现间接寻址。
(3)高级语言如Java,C#等没有指针,那他们怎么实现间接访问?答案是语言本身帮我们封装了。
3.1.3、指针使用三部曲:定义指针变量、关联指针变量、解引用
(1)当我们int *p定义一个指针变量p时,因为p是局部变量,所以也遵循C语言局部变量的一般规律(定义局部变量并且未初始化,则值是随机的),所以此时p变量中存储的是一个随机的数字。
(2)此时如果我们解引用p,则相当于我们访问了这个随机数字为地址的内存空间。那这个空间到底能不能访问不知道(也许行也许不行),所以如果直接定义指针变量未绑定有效地址就去解引用几乎必死无疑。
(3)指针绑定的意义就在于:让指针指向一个可以访问、应该访问的地方(就好像拿着枪瞄准目标的过程一样),指针的解引用是为了间接访问目标变量(就好像开枪是为了打中目标一样)。
#include <stdio.h>
int main()
{
/*
//这个内存空间就是a所代表的那个变量。
int a; //定义了int型变量,名字叫a;
int *p; //定义了一个指针变量,名字叫p,p指向一个int型变量;
a = 4; //可以操作;
p = 4; //编译器不允许,因为指针变量虽然实质上也是普通变量,但是它的用途和普通变量不同。指针变量存储的应该是另外一个变量的地址而不是用来随意存一些int类型的数。
p = (int *)4;//我们明知道其实就是数字4,但是我强制类型转换成int *类型的4
//相当于我告诉编译器,这个4其实是个地址(而且是个int类型变量的地址)
//那么(int *)4就和p类型相匹配了,编译器就过了。
*/
//演示指针的标准使用方式
//指针使用分3步:定义指针变量、给指针变量赋值(绑定指针)、解引用
int a = 23;
//第一步,定义指针变量
int *p;
printf("p = %p\n",p);//此时p中的值是随机的
printf("p = 0x%x\n",p);
//第二步,绑定指针,其实就是给指针变量赋值,也就是让这个指针指向另外一个变量
//当我们没有绑定指针变量之前,这个指针不能被解引用。
p = &a; //实现指针绑定,让p指向变量a
//p = (int *)4; //实现指针绑定,让p指向内存地址为4的那个变量
//第三步,解引用
//如果没有绑定指针到某个变量就去解引用,几乎一定会出错。
*p = 555; //把555放入p指向的变量中;
return 0;
}