初阶指针讲解

发布于:2022-12-12 ⋅ 阅读:(352) ⋅ 点赞:(0)

目录

1.指针是什么?

2.指针和指针类型

3.野指针

4.如何规避野指针

5.指针运算

5.1指针+-整数

5.2指针-指针

5.3指针的关系运算

6.指针和数组

7.二级指针

8.指针数组


1.指针是什么?

指针是内存中一个最小单元的编号,也就是地址

一个内存单元的大小是一个字节

平时口语中的指针,通常指的是指针变量,用来存放内存地址的变量

内存通过一个地址定位一个内存单元

指针变量:我们可以通过&操作取出变量在内存中的地址,把地址存放到一个变量中,这个变量就是指针变量

指针变量的大小与数据类型无关,只取决于CPU

32个比特位的地址:指针变量的大小4byte

64个比特位的地址:指针变量的大小8byte

例:int* pa = &a;

将a的4个字节的第一个字节的地址存放在pa变量中,pa是一个指针变量

存放在指针变量中的值默认为地址

2.指针和指针类型

指针类型决定了指针在被解引用的时候访问的权限

整形指针解引用访问4个字节

字符型指针解引用访问1个字节

我们看以上代码(注:char* pc = &a在VS2019会报错,所以我们进行一次强制类型转化)

我们发现:pa和pc的输出一样,但是pa+1和pc+1的值不一样

因为:指针类型决定了指针向前或向后走一步,走多大距离

int* +1 = +1*sizeof(int)

int* +n = +n*sizeof(int)

char* +n = +n*sizeof(char)

按照一个字节的形式访问

int arr[10] = { 0 };
int* p = arr;//首元素的地址
char* p = (char*)arr;
int i = 0;
for(i = 0; i < 40; i++)
{
	*p = 'x';
	p++;
}

按照一个整形的形式访问

int arr[10] = { 0 };
int* p = arr;//首元素的地址
char* p = (char*)arr;
int i = 0;
for (i = 0; i < 40; i++)
{
	*p = 0x11223344;
	p++;

}

 

3.野指针

野指针指的是指针指向的位置是不可知的

不可知是指随机的、不正确的、没有明确限制的

 产生野指针的情况:

  • 指针未初始化
int* p;//默认为随机值

*p = 20;//非法操作

指针未初始化就是没有给指针变量赋值,进行解引用操作时找不着指针所指向的内容,就会产生非法访问的警告

int* p = NULL;

给指针变量赋值为0地址就可以解决未初始化的问题

  • 指针越界访问

 由上图:数组arr只有5个元素,我们在循环时,循环进行了10次,p++到只想第五个元素时,就产生了数组越界访问,这种操作是非法的

  • 指针指向的空间释放

以上代码中,a是局部变量,出了函数销毁,地址空间返还给系统,不再属于程序 

所以在main函数中对p解引用访问其指向内容操作非法

4.如何规避野指针

  • 指针初始化
int* p = NULL;

当没有确定的指针赋给指针变量时,可以把0地址赋给一个指针变量

  • 小心指针越界

一般出现在数组的使用中,注意数组的大小即可

  • 指针指向空间释放即使之置为NULL,不用置空
  • 函数避免返回局部变量的地址
  • 指针使用之前检查有效性,非空可用
int a = 0;
int* p = &a;
if(p != NULL)
{
    printf("%p", p);
}

5.指针运算

5.1指针+-整数

指针+-整数:

vp+1:当vp为整形指针变量时,跳过四个字节;在一个整形数组中,假如vp指向第一个元素,vp+1就指向第二个元素,vp+2就指向第三个元素;*(vp+1)就可以访问到第二个元素

5.2指针-指针

指针-指针 = 两指针之间元素的个数

指针可以相减的前提:俩指针必须指向同一块空间

由程序运行结果:&arr[0] - &arr[9] = -9

所以可以推出:|指针-指针| = 两指针之间元素的个数

5.3指针的关系运算

标准规定:允许数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许指向第一个元素之前的那个内存位置比较

由监视窗口:可以看出该代码将values数组的元素全部初始化为0

第一段代码:
vp=&values[LEN]
前置--:vp-1,*vp=0,此时vp指向的是values[4]
......
当vp指向values[1]时,满足vp>&values[0]
前置--:vp-1,*vp=0,此时vp指向的是values[0]
vp>&values[0]不满足,跳出循环
在该段代码中,vp=&values[LEN],我们使用了超出数组范围的一个地址,但是并没有访问该地址所指向的内容,该操作合法
 

我们修改代码为下图:

第一次循环:vp=&values[LEN-1],*vp = 0,即values[4] = 0

vp--   vp = &values[LEN-2]     *vp = 0   即values[3]  = 0
.......

当vp = &values[0]时,*vp = 0,即values[0] = 0

此时循环没有结束,vp--,此时vp指向第一个元素之前的那个位置,这是标准不允许的,所以该操作非法

6.指针和数组

我们可以通过指针来访问数组元素

int*  = arr; //这里arr表示的数组首元素的地址

一般情况下,数组名表示数组首元素的地址 

有俩个例外:

sizeof(arr)/sizeof(arr[0]):arr表示的是整个数组,计算的是整个数组所占内存的大小

&arr:取出的是整个数组的地址

打印&arr时,虽然显示的是数组首元素的地址,但是&arr+1跳过整个数组

注意区分数组和指针:

指针是存放地址的变量

数组是一块连续的空间 

7.二级指针

 pa是指针变量

ppa是一个二级指针变量

 

8.指针数组

我们已经可以运用整型数组,字符型数组

整形数组:存放一系列整形数据元素的数组

字符数组:存放一系列字符型数据元素的数组

同理,指针数组就是存放指针数据的数组 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到