文章目录
- 内存
- 指针
- 指针的初始化
- 指针的目标
- 指针的解引用
- 指针的三种写法
- 指针的赋值
- 指针的大小
- 空指针
- 野指针
- 指针的作用
- 使程序简洁、紧凑、高效
- 有效地表示复杂的数据结构
- 动态分配内存
- 能直接访问硬件
- 能够方便的处理字符串
- 得到多于一个的函数返回值
- 学习方法
- 搞清楚原理
- 多编程、多画图
- 指针学习由易到难,逐层深入
- 基本功扎实,各种指针就不会混淆
内存
- 程序和数据存储在硬盘等存储器上,不管开机或关机,都是存在的
- 运行程序或打开数据时,这些数据必须从硬盘上先传到内存,之后才送入CPU进行执行处理。
- CPU直接从内存中读取数据,处理完成后将结果再写入内存

内存地址
- 在计算机中存储器的容量是以字节为基本单位的
- 为了方便存储和读取内存,内存的每个字节给一个编号
- 内存编号,也叫内存地址

变量的作用
- 变量用来在程序中保存数据
- 比如:
int k = 58;- 声明一个int变量k,CPU为k分配4个字节,可以存储数值58
指针
- 为了方便内存使用,内存的每个字节给一个编号
- 内存编号,也叫内存地址
- ① 指针就是内存地址
- ② 指针变量,是用来存放内存地址的变量
- 总结
- ① 指针即地址
- ② 口语中说的指针通常指的是指针变量
- 指针变量一般形式如下:
<数据类型> * <指针变量名> ;char *p ;- *指针运算符,表示定义的是一个指针类型的变量
- 数据类型,指针变量要保存地址,数据类型要和这个地址中保存的数据的数据类型保持一致。
指针的初始化
- 指针在说明的同时, 也可以被赋予初值,称为指针的初始化
- 一般形式:
- <数据类型> *<指针变量名> = <地址量> ;
int main() {int a = 10; int *p =&a;
}

指针的目标
- 指针指向的内存区域中的数据称为指针的目标
int a = 126;int *p = &a; // 指针p的目标是126
指针的解引用
int a = 126;
int *p = &a;
(*p)++;
- p,这里,官方称为“解引用”,意思是可以访问指针变量保存的地址了
- ()0xb012fe80,此时p == a,对*p进行加减乘除,也就是对a进行加减乘除,所以也称为“间接访问”

指针的三种写法
- 设p为一个指针,则:
- p 指针变量, 它的内容是地址量
- *p指针的目标,它的内容是数据
- &p指针变量占用的存储区域的地址,是个常量

指针的赋值
- 指针的赋值运算指的是通过赋值运算符向指针变量送一个地址值
- 向一个指针变量赋值时,送的值必须是地址常量或指针变量,不能是普通的整数(除了赋零以外)
- 指针赋值运算常见的有以下几种形式:
-
- 把一个普通变量的地址赋给一个具有相同数据类型的指针
-
- 把一个已有地址值的指针变量赋给具有相同数据类型的另一个指针变量
- float a, *px, *py;
- px = &a;
- py = px;
-
- 把一个数组的地址赋给具有相同数据类型的指针
- int a[20], *pa;
- pa = a; //等价 pa = &a[0]
指针的大小
- 对于32位的系统,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平和低电平。那么32根地址线产生的地址就是32个(1或者0)


- 232Byte==232/1024KB232/1024/1024MB==232/1024/1024/1024GB 4GB // 4G的空闲进行编址。
- 同样的方法,那64位机器给64根地址线,2^64Byte 。
- 32位的系统,地址是32个0或者1组成二进制序列,地址需要4个字节的空间来存储,一个指针变量的大小就是4个字节。
- 64位系统,有64个地址线,一个指针变量的大小就是8个字节
- uname -m命令,查看系统是多少位
空指针
- 不同于没有初始化的指针
- 在C语言中,NULL本质是0
#define NULL (void *)0 // 在C中NULL是强制类型转换为void *的0
- 指针如果没有给定初始值,值是不确定的
- 0地址是一个特殊地址,在一般的操作系统中都是不可被访问的,如果C语言程序员不按规矩(不检查是否等于NULL就去解引用)写代码直接去解引用就会触发段错误
野指针
- 指针指向的位置是不可知的(随机的、不正确的、没有明确指向的)
- 指向被释放的内存或者没有访问权限的内存的指针(非法访问)
野指针是怎么造成的
- 野指针的错误来源就是指针定义了以后没有初始化,也没有赋值(总之就是指针没有明确的指向一个可用的内存空间),然后去解引用
野指针的危害
- 野指针指向别的变量(指针所指向的那个变量)的地址
- 即指向了一个地址是不确定的变量,去解引用,结果是不可知的
- 野指针的错误来源就是指针定义了以后没有初始化,也没有赋值(总之就是指针没有明确的指向一个可用的内存空间),然后去解引用
- 段错误
- 指向不可访问(操作系统不允许访问的敏感地址,譬如内核空间)的地址,结果是触发段错误
- 程序错误被掩盖
- 指向一个可用的、而且没什么特别意义的空间(譬如我们曾经使用过但是已经不用的空间),这时候程序运行不会出错,也不会对当前程序造成损害这种情况下会掩盖你的程序错误,让你以为程序没问题,其实问题是非常严重的
- 程序出现离奇错误
- 指向了一个可用的空间,而且这个空间其实在程序中正在被使用(譬如说是程序的一个变量x),那么野指针的解引用就会刚好修改这个变量x的值,导致这个变量莫名其妙的被改变,程序出现离奇的错误。一般最终都会导致程序崩溃,或者数据被损害
如何避免野指针
- ① 定义指针时,同时初始化为NULL
- ② 在指针使用之前,将其赋值绑定给一个可用地址空间
- ③ 在指针解引用之前,先去判断这个指针是不是NULL
#include <stdio.h>int main() {int a = 10;int *p = &a;int b = 20;int *q = NULL;int t;printf("before:%d %d\n", a, b);q = &b;if (p != NULL && q != NULL) {t = *p;*p = *q;*q = t;}printf("after:%d %d\n", a, b);return 0;
}
- ④ 小心指针越界
- ⑤ 指针使用完之后,将其赋值为NULL
- ⑥ 避免返回局部变量的地址