文章目录
- 1.指针是什么
- 2.指针和指针类型
- 2.1指针的解引用
- 2.1指针类型的意义
- 3.野指针
- 3.1野指针成因
- 3.2如何规避野指针
- 4.指针运算
- 4.1指针+-整数
- 4.2指针-指针
- 4.3指针的关系运算
- 5.指针和数组
- 6.二级指针
- 7.指针数组
1.指针是什么
指针理解的2个要点:
- 指针是内存中一个最小单元的编号,也就是地址
- 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
指针变量
我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量
把a和pa的地址打印出来后,其实是一样的:
在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
2.指针和指针类型
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
2.1指针的解引用
2.1指针类型的意义
1.指针类型决定了指针进行解引用操作的时候,一次性访问几个字节,访问权限的大小
如果是char* 的指针,解引用访问1个字节
如果是int * 的指针,解引用访问4个字节
往后的几个类型,以此类推……
2.指针类型决定指针的步长(指针+1到底跳过几个字节)
字符指针+1,跳过1个字节
整形指针+1,跳过4个字节
3.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1野指针成因
- 指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
- 指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
- 指针指向的空间释放
3.2如何规避野指针
- 指针初始化
- 小心指针越界
- 指针指向空间释放,及时置NULL
- 避免返回局部变量的地址
- 指针使用之前检查有效性
int main()
{
int *p = NULL;
//....
int a = 10;
p = &a;
if(p != NULL)
{
*p = 20;
}
return 0;
}
4.指针运算
4.1指针±整数
4.2指针-指针
两个指针相减的前提是:两个指针要指向同一个空间
指针相减的绝对值等于两个元素之间的元素个数。
练习:
用strlen计算字符串:
用函数模拟strlen:
使用指针-指针代替上面的count:
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.指针和数组
指针和数组的关系:
指针和数组是不同的对象
指针是一种变量,存放地址的,大小4/8字节;
数组是一组相同类型元素的集合,是可以放多个元素的,大小是取决于元素个数和元素的类型的;
指针和数组的联系:
数组的数组名是数组首元素的地址,地址是可以放在指针变量中,可以通过指针访问数组;
6.二级指针
所以pa是一级指针
,ppa是二级指针
;
对于二级指针的运算有:
对ppa解引用得到的是*ppa=pa
;对pa解引用得到*pa=a
;
所以**ppa=a
;
7.指针数组
指针数组是一个存放指针的数组。
例如:
将其打印出来,也是和打印平常的数组一样:
再写一个指针数组: