⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:C语言初阶
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!

初识指针

  • 前言
  • 一、指针是什么
    • 1.内存
    • 2.指针变量
    • 3.知识点(解引用)
    • 4.编址是如何产生的
  • 二、指针和指针类型
    • 1.指针存储空间
    • 2.访问空间大小
    • 3.指针+-整数
    • 4.指针的解引用操作
  • 三、野指针
    • (一)野指针的定义和成因
      • 1.指针未初始化
      • 2.指针的越界访问
      • 3.指针指向的空间释放了
    • (二)野指针的规避
      • 1.指针进行初始化
      • 2.小心指针越界
      • 3.指针指向空间释放,及时置NULL
      • 4.避免返回局部变量的地址
      • 5.指针使用前检查有效性
  • 四、指针运算
    • 1.指针+-整数
    • 2.指针-指针
    • 3.指针的关系运算
    • 4.标准
  • 五、指针和数组
    • 1.指针和数组是不同的对象
    • 2.数组和指针的区别
  • 六、二级指针
    • 1.概念
    • 2.解引用操作
  • 七、指针数组
    • 1.概念
    • 2.偏代码操作
    • 3.常用代码
  • 总结

前言

刚开始大家对指针可能比较陌生,不像前面的函数数组那么好理解,可是指针是C语言的灵魂,指针让C语言常年霸占编译软件世界前三的位置,经久不衰,所以,接下来我会带大家认识一下指针,了解指针的基本原理和构造,相信大家学完这一篇博客,就会发现指针没有那么难,让大家对指针产生兴趣并充分运用指针。


一、指针是什么

两个要点:1.指针是内存中一个最小单元的编号,也就是地址。
2.平时大家所说的指针,通常是指针变量,是用来存放地址的变量。

1.内存

先理解一下内存:
顾名思义,内存就是电脑上的存储设备,大小一般是4G/8G/16G,在程序运行的过程中会加载到内存中,也会使用内存空间。
那先把我们的运行管理器拿出来看看(Ctrl+Alt+Delete):

那既然内存是存放程序的地方,是不是可以理解成一个个小抽屉去存放程序的,上图看看!

其实很好理解,一个内存单元相当于一个字节,而右边的16进制(也可其他进制)则是编号,相当于门牌号,加入你想找第三个内存单元,直接找它的编号(门牌号)即能找到,即寻址。

如上图所示,在不同的地方的叫法不一样,但是,其本质是一样的,编号就是地址,地址就是指针,他们是一回事。

2.指针变量

要理解指针变量,我们需要先理解一下取地址取的是哪个地址,取的是第一个字节,也就是较小的地址。

那接下来就有个疑惑了,这地址取出来有什么用,地址取出来不就只是一个简单的值吗?

因为pa是存放一个指针的,pa是根据取地址的那个变量的类型决定的。指针变量是一种变量,是专门用来存放地址的。

3.知识点(解引用)

#include<stdio.h>
int main() {int a = 10;int* pa = &a;//printf("%p\n", pa);//printf("%p\n", &a);*pa = 20; //*为解引用操作printf("%d\n",a);return 0;
}

4.编址是如何产生的

电脑是二进制运算的,以32位电脑举例,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(1)和低电平(0),那么32根地址线产生的地址是:

每一个二进制序列表示一个内存单元的编号,但这些编号是真实存在吗?答案是NO!它仅仅是计算机内部通过物理的电信号产生这个二进制序列,依据这个二进制序列去找相对应的内容。就好比人家给你在一张纸,上面写了他家的门牌号,你拿着纸吭哧吭哧去找,找到了以后这张纸丢了,你也不记得他家是那个门牌号了,因为没有经过保存,仅仅是一个信号而已。

解决完编号的问题,我们再来看一下内存的问题,32位机器是会产生2的32次方个地址,管理2的32次方个内存单元,也就是管理2的32次方个字节,先罗列一下换算表:

所以32根地址线存放了4个G的内存空间。
结论:在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
那如果是在64位机器上,如果有64根地址线,那一个指针变量的大小是8个字节,才能存放一个地址。


二、指针和指针类型

1.指针存储空间

在讲述指针大小之前,大家需要知道的知识点是int占4个字节,char 占1个字节,short占2个字节,double占8个字节。而指针类型只取决于机器是几位的,理由如上编址是如何产生的。

指针类型有没有一种固定的格式呢,就比如说ptr* 这种一个类型可以用所有的指针呢?答案肯定是不行的,如我们所见,指针类型有多种多样,int* ,float* ,char*等等,所以指针类型是有多样的。

用一串代码来解释一下:

#include<stdio.h>
int main() {int a = 0x11223344;int* p = &a;*p = 0;return 0;
}


如图,int* pa存的是44 33 22 11,至于为什么是倒着放,这是因为在数据结构里内存的大小端,这取决于编译器,后续博客我会给大家讲解到的。

大家可能有疑惑,这int类型不是占4个字节吗,这不是正好对应了吗,那换成比它小的short或者char呢?还是一样的吗?答案是一样能够存放的下,接下来上一串代码:

发现p和pc的值是一模一样的,说明指针变量的大小只取决于是几位的机器的。
那我们重复上面p的操作,利用解引用操作将pc的值改变成零看看是一种什么情况吧!

发现只改变了第一个字节。

2.访问空间大小

先要明白一个定义:指针类型是有意义的
指针类型决定了指针进行解引用操作的时候一次性访问几个字节,前提是要在同一个位数的机子下进行,*号前面是什么类型,则访问几个字节,所以当我们想要访问多大的空间,只需要用不同的指针类型访问即可。

3.指针±整数

指针类型决定了指针的步长(指针+1跳过几个字节)。
即:char指针+1,跳过1个字节;int指针+1,跳过4个字节,是不是很方便,只要你想访问几个几个字节,只需要用不同的指针类型进行访问,再解引用进行更换或替代值。

指针的不同类型,其实就是提供了不同的视角去观看和访问内存。
char* - 一次访问1个字节,+1跳过1个字节;
int* - 一次访问4个字节,+1跳过4个字节;

所以,指针的类型是什么,我就在访问内存空间的时候访问的是几个字节,这是完全取决于指针的类型的,与数值原本的类型无关。
举例:

4.指针的解引用操作

指针的类型决定了对指针解引用的时候有多大的权限(能操作几个字节)。
解引用以后存放的值是有限的,不是无限的,所以不能存放超过其内存大小的值。


三、野指针

(一)野指针的定义和成因

概念:是指指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。就相当于路边一只野狗,没有主人拴绳,你不知道它会怎么样,到那边走几步,到这边走几步,有可能还要咬人,这是不确定的,而野指针也是这样,是非常危险的,非常随机的。

1.指针未初始化


如上图就是一个野指针,假如当我喝醉后在大马路上随机进入一家,说,这个房间是我的,那这家主人肯定要把我赶出去,因为我没有在这个地方申请一个空间,这个地方本就不属于我,是随机去找的一个地方,是很危险的。
结论:指针未进行初始化就是个野指针。下图就是没有问题的指针使用。

2.指针的越界访问

顾名思义,越过所规定的边界去访问,就好比我越过了同桌在桌子中间画的线,那肯定要被他说的,但要是他没看见那不会,但他看见了,肯定会打我一下。这是非常危险的,如下图:

越界访问后,最后一个数是随机数。即:这个指针指向的位置不是合理已经划分的范围里,那就是一个野指针,指向的是一个随机的地址,那么值也是那个随机的地址的值。

3.指针指向的空间释放了

先来张图片再解释一下:

这个程序看似很正常,但是,大家想一想,是不是函数最后一个花括号结束以后函数的生命周期就消亡了,但p仍然会去找到a的地址,但实际上这是一个野指针,因为a已经走向生命周期的尽头了,已经消亡了。就好比我去住一个如花酒店的房间202,就开了一天的房间,我跟张三说,明天你来这个202房间住,我给你开了房住,张三脑海里存储了如花酒店202房间这个位置,第二天早上我把房间一退,回家去了,中午张三屁颠屁颠的来这个房间的这个位置,发现,人呢!?张三大喊我要住这个房间!那保安直接把他轰走。

(二)野指针的规避

1.指针进行初始化

int main() {int a = 10;int* pa = &a; //指针的初始化int* p = NULL; //空指针,相当于0 - (void*)0,是专门用来初始化指针的return 0;
}

NULL - 空指针,是专门用来初始化指针的,就相当于先把那条野狗先栓到树上,不让它乱跑,但也不一定意味着就绝对安全了,因为如果你去靠近这棵树并进行挑衅,那还是很危险的。如果定义了一个指针为空指针,但是去解引用进行改变值,那程序就会崩掉。因为p是指向的是一个空的地方。

2.小心指针越界

当我们在运用指针指向的数组空间的时候,注意不要越界即可。

3.指针指向空间释放,及时置NULL

如果一个指针指向的空间释放掉了,那我们需要把它赋一个空指针,让这个指针变得安全。

4.避免返回局部变量的地址

出了局部变量指针就会销毁,因为局部变量是有周期性的。

5.指针使用前检查有效性

在指针使用之前要判断这个指针是不是能用的,只有指针能用代码才能跑起来。


四、指针运算

1.指针±整数

指针vp每往后移动一位就赋一个位为0。

代码如下:

#define N 5
int main() {float values[N];float* vp;for (vp = &values[0]; vp < &values[N];) {*vp++ = 0;//*vp=0;//vp++;}return 0;
}

2.指针-指针

运算条件:两个指着要指向同一块空间,且指针的类型是一样的。

该程序结果是9,不是10,因为指针减指针所算出来的结果为两个指针之间的元素个数,利用指针的箭头发现,只有9个元素。如下图被涂成紫色的方块个数。

来个例子关于统计字符串个数,如下图所示:指针-指针得到的是两个指针之间的元素个数。

3.指针的关系运算

简单来讲,就是比较指针之间的大小,就和1.指针±整数里的代码一样,指针之间在进行相互的比较,再在循环里进行比较。

4.标准

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

如图:

解释越界但不非法:没有进行访问,只是超出范围,就相当于你不可以抢银行,但是允许在银行门口看看,转转,没抢银行,所以未非法访问,但确确实实是越界了。


五、指针和数组

1.指针和数组是不同的对象

指针是一种变量,存放地址的,大小是4/8个字节。
数组是一组相同类型元素的集合,是可以放多个元素的,大小是取决于元素个数和元素的类型的。

2.数组和指针的区别

数组的数组名是数组首元素的地址,地址是可以放在指针变量中。可以通过指针访问数组。
如下图:利用指针对数组内部元素赋值并进行打印。


优化:int* p=arr; p与arr首地址等价,所以arr[j]=*(p+j)= *(arr+j)= *(j+arr)=j[arr]; 原因很简单:[]是个操作符,而j和arr只是[]这个操作符的操作数而已。


六、二级指针

1.概念

二级指针就是取一级指针的地址,一级指针就是取原来数字的地址。

2.解引用操作


下图即为二级指针解引用后的值,与a的值一样。


七、指针数组

1.概念

指针数组是存放指针的数组,是一个完完全全的数组。

2.偏代码操作

举个例子,数组指针的操作:

3.常用代码

使用一维数组模拟一个二维数组。

int main() {//模拟一个三行四列数组int a[] = { 1,2,3,4 };int b[] = { 2,3,4,5 };int c[] = { 3,4,5,6 };int* arr[3] = { a,b,c };for (int i = 0; i < 3; i++) {int j = 0;for (j = 0; j < 4; j++) {printf("%d ", /**(arr[i]+j)*/arr[i][j]);}printf("\n");}return 0;
}


a,d,c表示的都是首元素的地址。


总结

大家从刚开始看到这里一定是对指针有了很深的理解,这篇博客从指针是什么往后讲到指针数组,总的来讲我们所说的指针就是指针变量,能够在内存中找一块空间,是很有趣的。


客官都看到这里了,来个三连支持一下吧!!!

【C指针】初识指针,轻松了解指针相关推荐

  1. (C语言)指针初识(1)——指针概念及指针类型

    指针,看似是一个令人头疼的问题,静下心来慢慢学习.指针这个主题,分成了几个的板块,比较多,耐心看完,一定会有收获啦!慢慢来,总是需要一个循序渐进的过程. 目录 一.什么是指针 二.指针和指针类型 指针 ...

  2. [C语言]static关键字--#define 定义常量和宏--初识指针--初识C语言(四)

    文章目录 前言 一,static关键字 二,#define 定义常量和宏 三,初识指针 总结 前言 本节主要记录初识C语言第四节内容. 内容包括:static关键字------#define 定义常量 ...

  3. 【C语言】深入理解数组和指针——初识指针

    哈喽大家好,我是保护小周ღ,C语言,接下来给大家带来的是深入理解数组和指针的初识指针,这篇主要讲的是基础指针的相关知识,是博主的所见所闻,细节上的知识后面会这里面没有提,会放在后期的文章中与数组相结合 ...

  4. 初识C语言---野指针

     野指针概念: 野指针就是指针指向的位置是不可知的(随机的.不正确的.没有明确限制的). 一.野指针成因 1.指针未初始化就使用 #include<stdio.h> int main() ...

  5. 【C语言】3天速刷C语言(指针初识)

    指针是啥 在计算机中,指针式编程语言中的与的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值.由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元.因此,地址形象化的称为&qu ...

  6. c语言指针的概念和作用,指针:C语言的重要概念和特色.pdf

    指针:C语言的重要概念和特色.pdf 一 指 针 :C语 言 的 重 要 概 念 和 特 色 令 小怀 (定西工贸中等专业学校 ,甘肃 陇西 748100) 摘 要 :指针是C语 言的精髓部分 .也是 ...

  7. C++ 笔记(27)— 指针变量、数组和指针、指针数组、数组指针、指针常量与常量指针

    1. 什么是指针变量? 指针变量是专门有一个变量来存放指针. int main(int argc, char *argv[]) {int a = 10;int *p = &a; //通过取地址 ...

  8. Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参

    1. 复合数据类型 Go 语言基本的复合数据类型有指针.数组.切片.字典.通道.结构和接口等.格式如下: * pointerType // 指针类型, [n]elementType // 数组类型, ...

  9. inline函数返回值_C++知识补充-指针,const,函数指针,指针数组,运算符重载

    嵌入式Linux:C++ 面试准备珍藏版本​zhuanlan.zhihu.com 明月照我心:123道c++笔试题汇总(含答案)​zhuanlan.zhihu.com 阿贵:常见C++笔试面试题整理​ ...

最新文章

  1. 函数动态传参详细,作用域和名称空间,global和nonlocal
  2. Java学习笔记_选择语句
  3. vue3 Cannot find module ‘path‘. 找不到模块‘path‘
  4. saefetchurl java_新浪云sae给的图片操作类
  5. 【实用】Putty常见错误汇总
  6. ●洛谷P2606 [ZJOI2010]排列计数
  7. Android 选项菜单
  8. 基于windows10+Anaconda3+Python搭建配置TensorFlow、Keras、Jupyter Notebook库,下载Kaggle狗猫数据集完成原始数据直接训练和数据增强后训练
  9. ⭐算法入门⭐《广度优先搜索》中等01 —— LeetCode 994. 腐烂的橘子
  10. 多径瑞利信道的一种matlab产生方法
  11. Excel怎么删除表格最后的空行
  12. 微信小程序组件之picker-view
  13. 超爆笑段子大集锦 你要不笑我自宫
  14. 微信小程序-编辑器插件
  15. 分享RTFM和STFW的意思
  16. 为什么手机网速太慢_为什么手机信号满格,网速却很慢?别再错怪手机了
  17. python的idle怎么运行_python中的idle是如何运行的
  18. nginx resin mysql_Nginx整合Resin
  19. 中国塑料土工格栅行业市场供需与战略研究报告
  20. 并联串联混合的电压和电流_混合断路器会成为高压直流电网故障清除的新出路吗?...

热门文章

  1. Chrome浏览器获取Google搜索结果批量URL
  2. 底层啊底层,你究竟是什么?
  3. 操作Python列表Ⅰ
  4. 用计算机sp画笑脸,用AI技术给名画P上笑脸,看上去整幅画的画风都不好了……...
  5. 用Python爬取购物节当天热门商品销量数据,看看大家喜欢什么
  6. 给设计师提供的十大无代码网站编辑器
  7. python通过ssh通道连接PostgreSQL数据库(mysql等类同)
  8. 5款知乎高赞的超牛软件,你一定要知道
  9. 本地spa应用的nginx简单配置
  10. 论文的正确打开方式—如何细读一篇论文分享