C语言--指针详解(一)

一.前言

下图是我所总结的思维导图,几乎涵盖了指针的所有知识点,带你深入了解指针。
为了控制博客的长度和质量我将分三篇来详细介绍,本章主要介绍指针&地址&内存指针变量,希望大家看完有所收获。

在这里插入图片描述

二.指针&地址&内存

  • 内存划分为一个个的内存单元
  • 每个内存单元都有一个编号,计算机把它叫作地址,C语言给地址取了个新名字–指针, 所以可理解为:内存单元的编号==地址==指针
  • 因为每个内存单元的大小是1个字节,所以每个字节都有编号,都有地址
  • 当说明变量时,系统将为其在内存中开辟相应的内存单元,由此确定变量的地址及内存中的表示方式
  • 如果有一变量p,其内容存放了a的地址 &a,通过p也可以实现对a的访问,则p称之为指针,并指向a

示例如下:

int a = 20;//变量创建的本质其实是在向内存申请空间
//int类型是向内存申请4个字节的空间,用来存放20这个数值,这四个字节,每个字节都有编号(地址)
//变量的名字仅仅是给程序员看的,编译器不看名字,编译器是通过地址找内存单元的

三.指针变量

3.1 定义

C语言中,指针变量是用来存放内存地址的变量,有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。指针描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。指向的对象可以是变量(指针变量也是变量)、数组、函数等占据存储空间的实体。

示例如下:
在这里插入图片描述

在这里插入图片描述

3.2 指针变量的大小与类型无关

  • 指针变量的大小与类型无关,取决于环境
int 占字节数指针占字节数操作系统可使用的最大内存空间
(x86)32位系统下442^32
(x64)64位系统下482^64

所以32位系统下任何类型的指针大小都是4个字节;64位系统下任何类型的指针大小都是8个字节

3.3 使用

  • 初始化:类型名* 指针变量名 = 变量地址值(&), 这里的*是指针声明符
  • *指针变量名,这里的*是解引用操作符(间接访问操作符)-- 获取指针所指向的内存地址上的值,当*符号出现在一个已经声明为指针类型的变量前面时,它将用作解引用操作符。

示例如下:

在这里插入图片描述

3.4 指针类型&指针所指向的类型

  • 指针类型:语法上看,只需去掉指针声明语句中的指针名,剩下的即为指针所指向的类型。
    -例如:
    ①int*ptr;//指针的类型是int*
    ②char*ptr;//指针的类型是char*
    ③int(*ptr)[3];//指针的类型是int(*)[3]
  • 指针所指向的类型:语法上看,只需去掉指针声明语句中的指针名和指针声明符*,剩下的即为指针所指向的类型。
    -例如:
    ①int*ptr;//指针所指向的类型是int*
    ②char*ptr;//指针所指向的类型是char*
    ③int(*ptr)[3];//指针所指向的类型是int(*)[3]

3.5 指针类型决定解引用权限

  • 指针的类型决定了对指针解引用的时候有多大的权限(一次能操作几个字节)
    char*的指针解引用就只能访问一个字节
    int* 的指针解引用就只能访问四个字节
    在这里插入图片描述

3.6 NULL

NULL在stdio.h的定义如下:

#if def_cplusplus //C++里
    #define NULL 0
#else   //C里
    #define NULL ((void*)0) // 可见,NULL指针是一个无类型指针,并且值为0
#endif
  • C语言中,NULL和0的值相同,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值。
  • 在不同的系统中,NULL并非总是和0等同,NULL仅仅代表空值,也就是指向一个不被使用的地址,在大多数系统中,都将0作为不被使用的地址,所以就有了类似这样的定义#define NULL 0。
  • NULL的出现是一种约定俗成,是C语言中定义的一个标识符常量,把一个指针赋值为NULL,通常的说法是“将指针悬空”,这样指针就无法再进行任何数据访问了,也就规避了野指针的存在。
  • 一个良好的习惯是:当一个指针的工作稍事休息,先把它赋值为NULL,待到再度使用时,重新对其赋值以及进行指针类型转化
  • 只要是NULL指针就不去访问,同时使用指针之前可以判断指针是否为NULL(检查有效性)

3.7 野指针

(1) 定义

指针指向的位置是不可知的(随机的、不正确的、没有明确限制的),即指针指向了一个地址是不确定的变量。此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的

(2) 成因

指针未初始化:任何指针变量刚被创建时不会自动成为NULL指针,因此当一个指针变量没初始化时其值是随机值,如果将其中存放的值当作地址,解引用时就会形成非法访问
指针越界访问:当指针指向的范围超出作用域的范围时,就会产生野指针
指针释放后未置空:有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。

(3) 使用野指针的严重后果

①指向不可访问的地址

危害:触发段错误。

②指向一个可用的,但是没有明确意义的空间

危害:程序可以正确运行,但通常这种情况下,我们就会认为程序是正确的没有问题的,然而事实上是有问题的,这样就掩盖了程序上的错误。

③指向一个可用的,且正在被使用的空间

危害:会对程序的运行产生影响,程序会崩溃,或者数据被损坏。

(4) 如何规避

①如果明确知道指针指向哪里就直接赋值地址
②如果不知道指针指向哪里可给指针赋值NULL
③指针变量不再使用时,及时置NULL

3.8 const修饰指针变量

  • 放*左边:限制*p(即指针指向的内容), 不限制p(即指针变量本身可以改变),示例如下:
int n = 10;
int m = 100;
int const *p = &n;
*p = 20;//报错
p = &m;//可以
return 0;
  • 放*右边:限制p, 不限制*p,示例如下:
int n = 10;
int m = 100;
int* const p = &n;
*p = 20;//可以
p = &m;//报错
return 0;

3.9 二级指针变量

定义:存放一级指针变量的地址

示例如下:

int a = 10;
int* pa = &a;//*代表pa是指针 指向的变量类型是int 所以pa是一级指针变量
int* * ppa = &pa;//ppa旁的*代表ppa是指针 指向的变量类型是int* 所以ppa是二级指针变量

在这里插入图片描述

四.总结

接下来我还会分两篇继续介绍指针(思维导图上剩下的部分),创作不易,希望大家多多支持,有什么想法欢迎讨论🌹🌹

  • 28
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值