C语言疑难杂症-指针

2022-06-07   大方老师单片机

原标题:C语言疑难杂症-指针

C语言疑难杂-指针

\\\插播一条:文章末尾有惊喜~///

进修阶段:高中信竞、大学编程。

前置知识:二进制与十六进制C语言根底,数组。

指针初学可能比较难了解,我这篇文章尽量用通俗易懂的方式来讲解。

1.指针概述

为什么有指针这个东西?由于指针很贴近计算机内部的实际工作原理,与内存实际的寻址方式类似C语言能够说是高级语言中最贴近机器的语言,而PythonJavaScript这种更亲和于人类的语言与机器的关系则比较远了,甚至它们自身可能还是C语言写出来的呢。

指针能够形象地比喻为在内存中定位的导航员。内存那么大,怎么知道我须要的东西存在哪里呢?能够让指针来记录与导航。我们先来了解一下内存。

2.预备知识

2.1内存

钻研过组装机、电脑配件的话,一定知道内存条这个东西。此时这个时代,一台家用电脑的内存一般2GB4GB8GB16GB32GB64GB等等。

CPU比作干活的人,则内存就相当于工作台CPU在跑的程序以及很多相关数据都存在内存内,这就相当于人在干活时要把相关资料放在工作台上使用。

内存能够看成是一个宏大的数组,我这里记为

memory[0..n]

memory的每一个单元1B=8bitmemory[0]就是内存的第一个单元。这个中括号里面的数,即数组下标,被称为内存地址,简称为地址。我确定了一个地址,也就相当于确定了内存中的一个单元。

通常,我们说32位机器,意思就是地址32bit的,最大支持的内存是

memory[0x00000000..0xFFFFFFFF]

最小地址0,最大地址0xFFFFFFFF=2^32-1,最大支持

也就是32位机器理论上最大支4GB的内存,这就是它渐渐被淘汰的理由。

64位机器理论上最大支持的内存是

这个量级远大于目前的需求,因128位机器在相当长的时长内不会出现。

2.2变量与数据类型

C语言有很多数据类型,不同的数据类型在内存中的占用空间和存储格式也不一样。不同数据类型的存储格式比较复杂,这里不详述。我只谈谈不同的占用空间。

一个变量在内存中占用都是不间断空间,T类型的变量在内存中占sizeof(T)字节的空间。当我声明一T类型的变a时,内存会寻找不间断且可用sizeof(T)个单元,把它们分配给变a,假如说memory[100..103]4B的空间。此后我对变a进行读写,也就相当于memory[100..103]4B的空间进行读写。

某些数据类型的占用空间short短整形占2Bint整形占4Bfloat浮点形占4Bdouble双浮点型占8Bchar字符型占1B.

3.指针

指针是一种特殊的数据类型,指针类型的变量应存储的是内存地址。32位机器上,任何一个内存地址都32bit=4B,故任何一个指针型变量都占4B.

此时问题来了,指针指向内存中的一个单元,我怎么知道这个单元里面存的是什么东西,是什么类型的数据?因此,在声明指针变量的时候,也要声明这个指针指向数据的类型,假int型指针char型指针等。

3.1指针的声明

在语法上,声明指针类型使*符号,例如

int *a, b, *c; //ac是指针b不是指char *ch;

这两句代码声明int*型的变acint型变bchar*型变ch.依据语法,我们习惯上T型指针T*型,含义就T*型变量是指针,其所指的相关内存单元存的T型数据(注意,这里b变量不是指针,仅仅为普通int整形。)

3.2指针的使用

指针有很多种使用方式,包括动态申请内存、函数地址传参等等。我这里仅介绍最简略的使用方式。我提供一份例程,可直接从例程中进修指针的声明与使用。

例程:

int x=1, y=2; //xy并赋初int *p=&x; //ppx*p=11; //pxp=&y; //py*p=12; //pyprintf("x=%d, y=%d", x, y); //xy

第一行,在内存中申请不间断4B区域存int型数1,记为变x;再在内存中申请不间断4B区域存int型数2,记为变y.x对应内存区memory[100..103]y对应内存区memory[200..203].第一行执行完毕,内存如1所示:

1第一行执行完毕

第二行在内存中申请不间断4B区域存int*型地址数100,记为变p.&符号是取地址运算符,表示取变x的首地址,在本例中就100.这一行代码是声明指针同时赋初值,相当于以下两行代码:

int *p;p=&x;

第二行执行完毕,内存如2所示100的十六进制0x64):

2第二行执行完毕

第三行,p所指的地址4B空间内存int型数11.*是解地址运算符表示取得指针所指的内存空间第三行执行完毕,内存如3所示:

3第三行执行完毕

假如第三行改为执p=(int*)11;,则是先int型数11强制转换int*型数11,然后赋值p,如3.2所示:

3.2第三行改为执p=(int*)11;

p所指的内存空间不一定是可用的。因此像这样直接给指针赋值一个常数的情况非常罕见。

第四行py的首地址。第四行执行完毕,内存如4所示:

4第四行执行完毕

第五行,把变y的值改12.第五行执行完毕,内存如5所示:

写文章

Keil系列教09_调试仿真

strongerHuang

?关注他

44人赞同了该文章

说明:

本文原创作者strongerHuang

首发于微信公众号‘嵌入式专栏’,同时也更新在我的个人网站EmbeddedDevelop

标签Keil MDK-ARMμVision

该教程基MDK-ARM,大局部内容也适用Keil3C51 C251 C166)产品。

一、写在前面

调试对于程序员来说是一个比较重要的环节,因此就很有必要掌Keil的这些调试功能。

Debug调试按钮,进入调试状态,就会出现如下Debug Toolbar调试工具栏。

我们调试须要用到的按钮包含上图框出来的这些按钮,但常用的按钮就是调试工具栏前八个:复位、全速运行、停下运行、单步运行、逐步运行、跳出运行、运行到光标行、跳转到暂停行。

二、相关描述

这些工具栏按钮的主要含义能够参看Keil系列教03_主窗口和工具栏详细说明》。

调试工具栏按钮位于菜Debug中,同时调试视图窗口位于菜View。能够参看文章Keil系列教04_菜单概述》。

同样,这些调试工具栏按钮可通过快速键实现,有些默认没有快速键,能够通Configuration添加快速键。请参看文章Keil系列教08_Configuration(二)Shortcut Keys快速键章节内容。

下面率领大家掌握那八个调试按钮、四个断点按钮,以及局部调试视图窗口的内容。

三、八个调试按钮

保证代码编译没误,点击/停下调试按钮(如下图),或快速Ctrl + F5,进入调试模式。此时就会出现如文中开头的调试工具栏。

3.1 Reset复位

Reset复位,让程序复位到起点,恢复到初始状态。

3.2 Run全速运行

Run全速运行F5),让程序处于运行状态。此按钮在程序停下运行时有效。

3.3 Stop停下运行

Stop停下运行,让正在运行的程序停下下来。此按钮在程序运行时有效。

3.4 Step单步运行

Step单步运行F11),每点一次按钮,程序运行一步(单步),遇到函数会跳进函数执行(箭头进入括号)。此按钮在程序停下运行时有效。

3.5 Step Over逐步运行

Step Over逐步运行F10),每点一次按钮,程序运行一行(单行),遇到函数跳过函数执行(箭头跳过括号)。此按钮在程序停下运行时有效。

3.6 Step Out跳出运行

Step Out跳出运行Ctrl + F11),每点一次按钮,程序跳出当前函数执行(箭头跳出括号),直到跳出最外面的函数main函数)。此按钮在程序停下运行时有效。

3.7 Run to Cursor Line运行到光标行

Run to Cursor Line运行到光标行Ctrl + F10),将光标放在某一行,点击该按钮,程序全速运行,直到运行到光标的位置停下下来。(前提是程序能运行到光标所在行)。

3.8 Show Next Statement跳转到暂停行

Show Next Statement跳转到暂停行,点击该按钮,跳转到程序暂停(停下)所在行。主要用我们翻开多个文件,不知道程序暂停在哪里。此按钮在程序停下运行时有效。

四、四个断点按钮

调试时,这四个按钮也常用,从左到右依次是:插/移除断点使/失能断点失能所有断点取消所有断点。

4.1/移除断点

Insert/Remove Breakpoint/移除断点F9),点击一下按钮,在光标所在行插入一个断点,再点击一次,则移除断点。

该按钮操作即是用鼠标在代码所在行前面点击一次,注意独有在灰色所在行才有效(也就是程序能执行的地方),如下图:

4.2使/失能断点

Enable/Disable Breakpoint使/失能断点Ctrl + F9),在有断点根底上,点击一下按钮,失能该断点,再点击一次,则使能该断点。

失能断点就是保留该断点,但该断点没效(程序执行到该处不停下)。

4.3失能所有断点

Disable All Breakpoints失能所有断点,保留所有断点,但都没效(和上面一个道理),但这里不能再次使能所有断点。

4.4取消所有断点

Kill All Breakpoints取消所有断点Ctrl + Shift + F9),和上面失能不一样,这里是不保留断点,即取消工程所有断点,也叫杀掉所有断点。

五、调试视图窗口

调试视图窗口独有进入调试模式时才会出现,其窗口名称详情可参看文章Keil系列教04_菜单概述》View菜单章节。

这里讲述几个在调试时常用的视图窗口。

5.1 Watch窗口

Watch查看变量的窗口,Watch1Watch2两个窗口,都一样,方便用户多个窗口同时查看。

查看这些调试视图窗口能够通过菜单,或点击工具栏按钮翻开。

选中变 -> -> Add xxx to ->Watch1,此时自动会弹Watch1窗口:

5.2 System Viewer窗口

System Viewer系统(外IOUSARTTIM等)窗口,能够了解查看外设寄存器的窗口,如下图,查USART寄存器值的窗口。

这些调试视图窗口只针对于调试时,方便大家查看一些调试信息,掌握这些内容会提高你的调试效率,以及更精确定Bug

六、说明

1.该文档仅供个人进修使用,版权所有,禁商用。

2.本文由我一个人编辑并整理,难免存在一些错误。

彩蛋:最近有同学跟我要单片机的资料,我特意花几个月时间,总结了我10年产品研发经验,资料包几乎覆盖C语言、单片机、模电数电、原理图PCB设计、单片机高级编程等等,非常适合初学者入门和进阶。除此以外,再含泪分享我压箱底22个热门开源项目,包含源+原理+PCB+说明文档,不是市面上打包卖的那种课程,我认为教程多未必是好事10年前我自学快,除了自身执行力以外,还有就是教程少。不要害羞做伸手党,等你一个小红点。后期我也会组建一些纯技术交流的小圈子,让大家能认识更多的大佬,有个好的圈子,你对行业的认知一定是最前沿的。