1.指针和地址
指针:指针在c语言中属于一种类型,这种类型对应的变量专门用于存储地址
地址:存储单元的编号,用于区分不同的存储单元,存储在内存中的每个数据都会有地址
例如:char ch;//分配一个字节 short a;//分配两个字节
注意:地址是一个常量
2.直接引用与间接引用
直接引用:表示通过变量名来引用(对变量读与写)
间接引用:通过指针类型变量来引用,即将变量地址存储到指针变量中
√:使用*来表示指针类型
定义指针类型的变量:< 类型修饰符> * 变量名
例如:
理解:P是地址;*P是一个值 int*p是一个地址
注意:任何类型必须定义变量之后才会分配空间
区分:
一个指针变量所占用的空间,和操作的地址总线(硬件)的宽度有关系,一般为32位/64位,操作系统本身的能够一次处理的数据大小有关
3.指针变量的初始化
指针变量在使用时,一定要指向一个确定的存储空间(赋值或者初始化),否则指向的位置是随机的(称为“野指针”)。如果不确定指针类型变量所指向的空间,可以初始化为NULL,如:int *p=NULL
注意:int *p=1000(错误) 在有操作系统的情况下,不能给指针初始化一个常量
补充:如果不确定指针类型变量所指向的空间,可以初始化为NULL,对指向NULL的指针进行间接运算会产生"段错误",解决方法如下:
Segmentation fault (core dumped) //出现段错误
Gdb //来确定是第几行
gdb a.out
执行 r 命令
Program received signal SIGSEGV, Segmentation fault.
0x08048409 in main () at 03pointer.c:7
7 *p = 300;
(gdb) q
4指针变量作为函数参数
使用指针类型的变量作为函数的形式参数,与普通变量的语法相同,写成指针类型即可
例如:void swapy(int *pa,int *pb);
使用的指针类型的变量作为函数参数,实际参数需要指定为地址或者其他的指针变量,同时,形式参数也分为输入的形式参数与输出的形式参数
输入的形式参数,一般将实际参数的值传递给形式参数
输出的形式参数,一般通过指针进行间接引用,可以返回调用这多个值
作用:主要用于解决:return 只能返回一个值的问题
具体例子(常用):output 函数的应用
5指针与一维数组
数组及其元素同样占有存储单元,都有相应的地址,所以指针即可以指向数组的元素,也可以指向数组
区别:数组名与数组首地址的区别
作用:
每个形式参数都需要分配空间,而且是独立的空间
如果将数组整体进行传递时,产生一个形式参数数组,非常浪费空间与时间
将数组的首元素的地址进行传递
6.指针运算
当指针指向一段连续内存空间某一个地址时,比如指向数组元素时,就可以进行指针元素,一 般可以进行如下的运算:
自增/自减运算:进行加1运算与减1运算
求差值:两个指针变量进行减法运算,前提是指向同一段内存空间
赋值:将一个地址赋值给一个指针
定义一个一维数组与指针变量,并进行指针运算,包括++ / -- ,指针-指针,指针-数字
注意: int *ptr++ 先取值后++;
例子:Int i; int p=&I;
补充:(技巧性)追逐法确定第一、第二个最大值
7.指针与二维数组
C语言把二维数组看作是一维数组的集合,即二维数组是每一个元素为一维数组的特殊一维 数组,即二维数组的元素类型为一维数组
理解:二维数组的首地址---一维数组的首地址---一维数组的元素的地址---元素的值
一个*或[ ]降一级 一个&升一级
区分:
注:图2最后一行错误
8.指向一维数组的指针
指针变量存储的地址对应的变量的类型一般使用类型修饰符来确定
指针与二维数组的结合,一般为了方便操作行,就是需要使用指向一维数组的指针
指向一维数组的指针,用于存储数组的地址(不是数组元素的地址)
例如:
9.指针数组
指针数组主要用于存储地址的集合,每个元素都是存储的一个地址
应用:
补充:(函数性)strcmp 用于字符串比较
补充:(技巧性)冒泡排序法
字符串的排序:
10.指向指针的指针
存储指针变量的地址,使用指向指针的指针
具体例子:
11. void *类型的指针
int *p ;//计算偏移 +1 偏移4个字节,在进行间接引用运算(寻址运算),操作4个字节
char *p ;//计算偏移 +1 偏移1个字节,在进行间接引用运算(寻址运算),操作1个字节
void *q ;//表示无类型的指针,可以存储任何类型的地址,存储时转换成void *
void *的指针不允许进行间接引用操作,因为不知道会操作几个字节
作用:在函数中作为形式参数时,可以提高对应的通用性
int *p = (int *)q;//指针类型的强制转换
具体例子: