目录
间接寻址:通过存放变量地址的其他变量访问该变量(通过其他变量间接找到变量的地址读取变量的值——*)
前言:
强转与指针,并称C语言的两大神器,用好了可呼风唤雨,威力无比,用不好也会伤及自身
理解指针要从变量的地址谈起
(1)内存是如何编址的?
- 内存中的每个字节都有唯一的编号(地址)(如同街道的门牌号),内存地址按字节编号,其字长一般与主机相同, 32位机使用32位地址,最多支持232字节内存(4G )
- 地址是一个无符号整数,从0开始,依次递增。在表达和交流时,通常把地址写成十六进制数
(2)如何对变量进行寻址?
-
直接寻址:直接到变量名标识的存储单元读取变量的值——&
-
间接寻址:通过存放变量地址的其他变量访问该变量(通过其他变量间接找到变量的地址读取变量的值——*)
-
关于直接寻址的两个问题:
问题一、
int i;
scanf("%d", i); /* 这样会如何?*/
i 的值被当作地址。如i值为100,则输入的整数就会从地址100开始写入内存
问题二
char c;
scanf("%d", &c); /* 这样呢?*/
输入数据以int的二进制形式写到c所在的内存空间。c所占内存不足以放下一个int,其后的空间也被覆盖
(3)用什么类型的变量来存放变量的地址?——指针类型
- 指针类型为4个字节大小
- 指针变量:具有指针类型的变量
- 指针变量基类型:指针变量指向的数据类型,称为基类型(指针变量只能指向同一基类型的变量,否侧会引起warning)
int *pa;//定义的一个可以指向整型数据的指针变量
//*号:表示pa是一个整型指针变量
//定义之后就可以用它保存一个整型变量的地址了
//告诉编译器,pa是一个指针变量,占4字节内存,需要用一个int型变量的地址给它赋值,
(4)指针究竟指向了哪里?——指针变量初始化
- 使其具体的指向某一个变量
int *pa = &a;//指针变量初始化 //等价于int *pa;pa=&a
未初始化带来的危害:
- 指针变量未被初始化,意味着指针变量的值是一个随机值,我们无法预知它会指向哪里,它很可能会乱指一气。使未初始化的指针变量是初学者常犯的错误,其带来的错误隐患是非常严重的。在不确定指针变量究竟指向哪里(也许是一个只读的或者不可访问的存储区,例如待执行的机器指令所在的代码段)的情况下,就对指针变量所指的内存单元,进行写操作,将会给系统带来潜在的危险,严重时还会导致系统崩溃
- 如果你不知把它指向哪里,那就指向NULL
int a = 0, b = 1;
char c = 'A';
int *pa = NULL, *pb = NULL;
char *pc = NULL;
(5)空指针:
- Þ每个C编译器都被允许用不同的方式来表示空指针
- Þ并非所有编译器都使用0地址
- Þ某些编译器为空指针使用不存在的内存地址
- Þ硬件会检查出这种试图通过空指针访问内存的方式
(6)指针变量与变量的地址的区别:
(7)如何访问指针指向的存储单元中的数据?
——指针的解引用:引用指针指向的变量的值,修改指针变量pa所指向的变量的值(修改存储单元中的数据)
(8)指针的简单使用
典型实列:两数互换
- 按值调用:普通变量作函数参数—按值调用 实参的值不随形参值的改变而改变
- 按地址调用:指针做函数参数—按地址调用 为了在被调函数中修改其无法直接访问的实参的值
注意:某些编译器检查实参和形参的数据类型是否匹配,不匹配则给出警告;另一些编译器直接将实参的值当作地址值,产生非法内存访问,导致程序异常终止
(9)什么是函数指针?
函数指针就是指向函数的指针变量,指向函数的指针变量中存储的是一个函数在内存中的入口地址
通过前面的学习可以知道:一个数组名其实就是存储数组第一个元素的内存地址。同理,一个函数名就是这个函数的源代码在内存中的起始地址
定义格式:数据类型(*指针变量名)(形参列表);
列如:若有函数原型为:int Fun (int a , int b);
则可定义函数指针: int (*f) (int,int) ; 令f=Fun;就是让f指向函数Fun()
——编译器将不带()的函数名解释为该函数的入口地址
——函数指针变量存储的是函数在内存中的入口地址
定义函数指针常见错误:
(10)函数指针的应用:
实列一:编写通用性更强的函数
典型实列二:编写通用的排序函数——编写实现升序和降序排序
(11)总结:
——指针变量 :
- –指针类型的变量,保存地址型数据
——指针变量与其他类型变量的共性:
- –在内存中占据一定大小的存储单元(通常4个字节)
- –先定义,后使用
——特殊性
- –指针变量中保存的内容只能是地址(变量或函数的地址)
- –必须初始化后才能使用,否则指向不确定的存储单元
- –只能指向同一基类型的变量
- –可参与的运算:加、减整数,自增、自减、关系、赋值
——指针变量
- 定义不同基类型的指针,是明确指针指向单元的内容是什么
- 初始化的目的,是明确指针指向了哪里
——使用指针变量的基本原则
- 明确指针指向了哪里
- 明确指针指向单元的内容是什么
- 永远不要使用未初始化的指针变量
- 一个(xx型)的指针指向一个(xx型)的变量
——指针的一个重要应用之一
- 作函数参数,向函数传递变量或函数的地址
——指向变量的指针,作函数参数
- 按地址调用,传递变量在内存中的地址(用取地址运算符)
- 被调函数根据该地址读写它不能直接访问的变量的值(用间接寻址运算符,指针的解引用)
——指向函数的指针,作函数参数
- 按地址调用,传递函数在内存中的入口地址(函数名)
- 被调函数根据传入的不同地址调用不同的函数