目录
4.2.2.例子(※)
1.指针是什么
指针理解的2个要点:1. 指针是内存中一个最小单元的编号,也就是地址2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量总结:指针就是地址,口语中说的指针通常指的是指针变量
1.1.内存
内存
注:
1.内存被划分为一个个小的内存单元
2.一个基本的内存单元的大小是一个字节
3.内存单元的编号被称为是一个地址,地址也称为指针。(内存单元编号=地址=指针)
4.编号的产生:现在有32位机器和64位机器,以32位机器为例
32位机器有32跟地址线(物理电线),物理电线通电,通电后会有高电平和低电平,转化为数字就是1/0。 32跟地址线会产生不同的32位数字,如下
00000000000000000000000000000000
00000000000000000000000000000001
......
11111111111111111111111111111110
11111111111111111111111111111111
将这些编号作为内存单元的编号,即地址,也就是指针
5.这32根地址线可以产生个32位数字,一个32位数字作为一个地址可以产生
个地址 ,一个地址管理一个字节,个地址可以管理个字节空间,转化为十进制数为4294967296
4294967296 byte(字节)=4194304 KB= 4096 MB=4 GB
6.32位数字作为地址需要32个bit(比特)空间来存储,而32个bit空间是4个字节,所以存一个地址需要4个字节空间,一个指针变量就是存储该地址,因此一个指针变量占4个字节。如下图(同理若在64位机器下一个指针变量就需要8个字节来存储)
1.2.编译器中解释地址
注:
1.内存中第一列显示的是地址,第二列是内存数据布局,第三列是以ASCII的形式解析第二列内存中的数据(不一定准确)
2.第二列中0a 00 00 00就是变量a所占的四个字节,其中每相邻的两位各占一个字节,
10的二进制数为:00000000 00000000 00000000 00001010
10转换为16进制数为:00 00 00 0a
内存里就是将该16进制数倒着放进去了(内存中存的是2进制数,只不过显示时显示十六进制)
当我们把显示列数改为1时,就更容易理解了,如下图
1.3.地址的使用
1.打印地址
2.存储地址
注:
1.这里的*pa就是指针变量(通常口头上叫做指针)
2.当a是四个字节的时候&a其实拿到的是这四个字节中第一个字节的地址
3.int* pa其中,*代表pa是一个指针变量,前面的int代表该指针变量指向的变量的数据类型
2.指针和指针类型
2.1.指针+-整数
注:
1.虽然指针类型不一样,但是他们都是申请四个字节空间,里面存的地址是一样的
2.指针类型的意义决定了指针向前或者向后走一步,走多大距离(单位是字节)
整型指针向后走一步走了4个字节
字符指针向后走一步走了1个字节
2.2.指针的解引用
注:
1.虽然不同的指针类型都是创建4个(8个)空间来存储指针变量的,但是其本质是有差别的
2.指针类型的意义决定了在解引用时一次能访问几个字节(指针的权限)
char* 决定解引用能访问 1个字节
int* 决定解引用能访问 4个字节
float* 决定解引用能访问 4个字节
double* 决定解引用能访问 8个字节
2.3.例子
描述:
创建一个整型数组,10个元素
1.初始化数组的内容是1-10
2.倒着打印数组内容
3.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1.野指针成因
注:对指针变量p没有初始化,所以p没有指向任何固定对象
注:当i=10时,指针变量p会越界访问到数组后面的一个整型空间,此时指针变量p变成一个野指针
3. 指针指向的空间释放
注:这里指针变量p指向了a空间,但是函数调用完后,a地址的使用权限被收回去了,再通过p来访问该地址,该地址已经不属于这个程序了,此时p称为野指针。
3.2.如何规避野指针
1. 指针初始化2. 小心指针越界3. 指针指向空间释放及时置 NULL4. 避免返回局部变量的地址5. 指针使用之前检查有效性
1. 指针初始化
2. 小心指针越界(不要出现下面越界的访问)
3. 指针指向空间释放及时置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
注:
1.指针为空,我们不去使用它,指针不为空,我们再去使用它。
2.空指针是不允许去访问的
4.指针运算
指针 +- 整数指针 - 指针指针的关系运算
4.1.指针 +- 整数
4.2.指针 - 指针
4.2.1.指针 - 指针
注:
1.两个地址相减的绝对值得到的是这两个地址间元素的个数
2.指针 - 指针 的前提是两个指针指向同一块空间,下面代码是错误的。
int a = 10;
char c = 'w';
&a - &c; //err
4.2.2.例子(※)
描述:
用指针 - 指针的方法模拟strlen函数
4.3.指针的关系运算
for(vp = &values[N_VALUES]; vp > &values[0];)
{
*--vp = 0;
}
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
*vp = 0;
}
注:指针只是访问数组外元素,这不是越界
5.指针和数组
数组和指针本身是两种事物
联系就是:可以通过指针来访问数组
6.二级指针
知识点一:
注:
1.int** ppa中两个*中后面的*是单独的,表示ppa是一个指针,前面的*和int是一组,因为ppa指向的是pa,而pa的数据类型是int*,所以这里应该是int*(ppa指向谁,*的前面就写谁的数据类型)(int*** pppa同理)
知识点二:
注:对ppa进行一次解引用指向指针变量pa,再进行解引用就指向了变量a
7.指针数组
存放指针的数组
注:
1.指针数组不完全初始化,其他指针默认为空指针NULL(0和NULL是完全一样的)
2.arr3是一个数组,有五个元素,每个元素是一个整形指针