这里更多探究的是指针的机制。

debug对下面程序进行分析,记录每一条C语句运行后,相关内存单元的值。

程序a.c

注意理解指针机制

我们编写如下代码:

编译加载进debug查看:

我们先看其反汇编的代码:

在这里我们对比着C语句分析:

第一条语句是将1000H(16进制,以下16进制用H说明,未说明的都为十进制数据。且汇编语言数据都为16进制,不加H说明。)。放置在变量P(偏移地址01FAH)处。

第二句中,使用*的地方,即*p处,这里的语句被翻译成两句,即:MOV BX,[01FA]和ADD AL,[bx]。在这里我们知道,在汇编中,[]代表的是地址,也就是说先将01FAH地址处的数据放到BX中然后在将DS:[BX]中的数据加到AL中。

第三句中,在使用&处的语句,即p=&ch;处,我们看到在上条语句中,AL最后放到了01A8H处,也就是01A8H处是ch的存放位置。我们看到,p=&ch;这条语句被翻译成了:WORD PTR [01FA],01A8。也就是说,将ch在内存中的存放位置这个数,放在了DS:[01FA]处。从这里我们能看出。1.指针类型也是存放在内存中,存放的内容是一个地址。2.指针类型是一个2字节的。

第四句中,是用*P处。我们看到,首先,将p的地址中存放的地址(也就是ch所占的内存),放到BX中,然后将DS:[BX]的数据放到al中,inc al。我们可以看到,*指针所对应的操作是取指针指向的内存处的数据。

第五句,这里看到了双指针,我们来看,分析上下文我们得出,这句赋值的语句被翻译成了MOV BX,[01A6] 我们看到,这里是将指针P的地址放在了pa中。

我们查看单步执行的过程,对比我们的分析:

在这里我们看到,第一二句执行的时候,确实是将1000H处的数据放到了AL中,也就是P指向的位置的数据。

在这里我们看到,对*p的处理,是将指针内的数据给BX,并将DS:[BX]处的数据放在AL中。

我们看到,这里是将指针p的地址给了pa。

这里调用的时候,是先将01A6H处的数据传给BX,再将DS:[BX]处的数据放到BX中,也就是说*的作用是将这里的数据当做地址向外拿数据。

在这里我们看到char far*,在放入地址的时候,将DS也放入的进去,这里也可以说明far型的指针变量的大小为四个字节。

而且,指针变量还可以被转换为int型的变量。转换过后,是将指针指向的地址作为int型变量的值。

*(char *)n这里是将n的值作为地址,取这里的char型的值。

综合来看,指针是一种特殊的类型,指针内存放(这里是指针内,存放)的是一个地址。他有2字节和4字节两种形式。&是取地址符,*是取指针指向位置的数据。

程序b.c

注意Struct指针的用法,指针“+”运算的意义。

我们编写程序如下:

我们在反汇编后看到,首先,pstuàname[1]与((*pstu).name[2])在翻译过后的形式是一样的,都是MOV BYTE PTR [ ], 这样的形式。也就是说他们的功能是一样的。其次,对于Struct指针,记录的是Struct的首地址。最后,当指针做“+”运算的时候,其实加上的不是定值,而是它所指向的类型的长度。对于char型是1,对于int型是2,对于自定义类型,是其自定义的数据的长度之和。

我们查看单步的情况:

那么,这样做的意义在哪儿?指针自加,所加上的是其指向的数据类型的长度,那么我们就可以方便的在程序中使用指针,也可以在循环中使用指针。并且,这样的方式使得程序寻找内存的方式更加多样,更加灵活。

程序c.c

注意理解“[]”运算的意义及数组名与指针的关系。

从整体来说,在这里我们可以看出,p的地址是01d0H,pf的地址是01ceH和01ccH;str的首地址为01caH,而01caH里边存的数据是字符串的首地址0194H;a的首地址为01a8H。

我们可以分析出的一个for循环的位置,是从0206H到022eH。

将01CAH(01CA中结合上下语句可以看出是放的N)处的数据放在BX中,然后将BX+0194H处的数据放到AL中,即是数组中的值。 01caH处放的是pf+n的数据,*(pf+n)就是将[1ca]给了bx,然后将al给了[bx],完成在0:200中写入字符串。

第二个for是024AH到026AH,这里我们可以看出*(str+n)功能与*str+*n是相同的。

第三个for是从026EH到029BH,这里我们看出,其inc WORD PTR[01AC]这条指令被替换成了两条指令:SHL DX,1 shl bx,1和inc word ptr [01CA]。这是因为所取的数据变成了int型。

第四个for,在实现上与第三个for是类似的。

综合来看,数组在底层的实现过程和指针在底层实现的过程是一样的。数组名就相当于指向数组空间首地址的指针。而‘数组[下标]’的方式就相当于‘指针+数据类型长度*下标’的方式。

深入研究C语言 第四篇的更多相关文章

  1. 深入研究C语言 第三篇

    本篇研究TC2.0下其他几个工具.同时看看TC由源代码到exe程序的过程. 1. 用TCC将下面的程序编为.obj文件 我们知道,TCC在默认的编译连接一个C语言的源程序a.c的时候分为以下两步: ( ...

  2. 深入研究C语言 第一篇(续)

    没有读过第一篇的读者,可以点击这里,阅读深入研究C语言的第一篇. 问题一:如何打印变量的地址? 我们用取地址符&,可以取到变量的偏移地址,用DS可以取到变量的段地址. 1.全局变量: 我们看到 ...

  3. Flask最强攻略 - 跟DragonFire学Flask - 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法

    是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...

  4. flask 第四篇 模板语言jinja2

    是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...

  5. R语言学习 第四篇:函数和流程控制

    变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用.在R中,函数只是另一种数据类型的变量,可以被分配,操作,甚至把函数作为参数传递给其他函数.分支控制和循环控制,和通用编程语言的风格很相似, ...

  6. 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)

    解剖SQLSERVER 第十四篇    Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...

  7. RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  8. 第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

  9. [老老实实学WCF] 第四篇 初探通信--ChannelFactory

    老老实实学WCF 第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF的服务端-客户端模型,可以建立一个简单的WCF通信程序,并且可以把我们的服务寄宿在IIS中了. ...

随机推荐

  1. Hibernate多对多双向关联

    以Student和Course为例,一个学生可以选多门课程,一门课程也可以被多个学生选取: 持久化类Student: package bean; import java.util.Set; publi ...

  2. git和github

    GIT是一款分布式版本控制系统.与SVN相比可以不依赖网络,并且对分支和合并有更好的支持.但是命令稍微复杂一些,这里简单介绍使用git将项目上传到github. 首先GIT安装只需要去官网下载安装即可 ...

  3. ConCurrent in Practice小记 (1)

    ConCurrent in Practice小记 (1) 杂记,随书自己写的笔记: 综述问题 1.线程允许在同一个进程中的资源,包括共享内存,内存句柄,文件句柄.但是每个进程有自己的程序计数器,栈和局 ...

  4. 在 Windows 環境下利用 VNC 遠端控管 Mac OS X Server

    Mac OS Server 可以使用 VNC 來遠端控管.不過,在 Mac 上打開這個功能很簡單,要讓 Windows 的 VNC Viewer 連上卻很難,原來是有原因的. 首先我們來看怎麼在 Ma ...

  5. 配置移动前端开发调试环境(nodejs+npm+weiner的安装和配置使用)

    这段时间发现做移动端的开发调试是一大难题,网上逛了逛发现有一些工具可用,如chrome的远程调试,实际测试过程中我始终调试不成功,听说被墙后是不行的,所以最终找了如下的方法. 因为基于nodeJS环境 ...

  6. 现在开始(Do It Now)

    现在开始(Do It Now) 很多年前读大学的时候,我决定制定一个计划挑战自己:只用三个学期完成其他人通常花费四年的课程,能否毕业.这篇文章(此文为翻译)详细的说明了我在成功实现该目标过程中的所有时 ...

  7. EBS 消息总线

    http://www.ibm.com/developerworks/cn/webservices/ws-whyesb/ 开发人员为何需要企业服务总线? 本文不仅仅是为架构师准备的:使用企业服务总线 ( ...

  8. 粒子拼字效果(getImageData方法)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Device eth0 does not seem to be present, delaying initialization. 问题

    今天在复制vmware的时候 出现网卡无法启动 报错显示 Device eth0 does not seem to be present, delaying initialization. 这个错误原 ...

  10. 401 Not Authorized For MSDEPLOY‏ (msdeployAgentService)

    When you get this error from msdeploy:“Error: The remote server returned an error: (401) Unauthorize ...