深入研究C语言 第四篇
这里更多探究的是指针的机制。
用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语言 第四篇的更多相关文章
- 深入研究C语言 第三篇
本篇研究TC2.0下其他几个工具.同时看看TC由源代码到exe程序的过程. 1. 用TCC将下面的程序编为.obj文件 我们知道,TCC在默认的编译连接一个C语言的源程序a.c的时候分为以下两步: ( ...
- 深入研究C语言 第一篇(续)
没有读过第一篇的读者,可以点击这里,阅读深入研究C语言的第一篇. 问题一:如何打印变量的地址? 我们用取地址符&,可以取到变量的偏移地址,用DS可以取到变量的段地址. 1.全局变量: 我们看到 ...
- Flask最强攻略 - 跟DragonFire学Flask - 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法
是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...
- flask 第四篇 模板语言jinja2
是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...
- R语言学习 第四篇:函数和流程控制
变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用.在R中,函数只是另一种数据类型的变量,可以被分配,操作,甚至把函数作为参数传递给其他函数.分支控制和循环控制,和通用编程语言的风格很相似, ...
- 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)
解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...
- RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- 第四篇 Integration Services:增量加载-Updating Rows
本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...
- [老老实实学WCF] 第四篇 初探通信--ChannelFactory
老老实实学WCF 第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF的服务端-客户端模型,可以建立一个简单的WCF通信程序,并且可以把我们的服务寄宿在IIS中了. ...
随机推荐
- zookeeper dubbo 问题解决录
问题1: 运行起来不报错,不过在Console没有zookeeper的心跳信息,也就是说没有配置上zookeeper,而出错的原因是下面蓝色这段解析不了 spring-dubbo-provider.x ...
- XidianOJ 1057 卡尔的技能
题目描述 dota中的英雄卡尔的技能说明如下,他拥有3种不同的元素(冰,雷,火),每次他需要释放技能的时候,他要先选择3次元素来决定释放技能的类型(比如,他可以选择火+火+火或冰+雷+火等等),生成技 ...
- 如何决定DCOM是否可用
如何决定DCOM是否可用
- 在 Windows 環境下利用 VNC 遠端控管 Mac OS X Server
Mac OS Server 可以使用 VNC 來遠端控管.不過,在 Mac 上打開這個功能很簡單,要讓 Windows 的 VNC Viewer 連上卻很難,原來是有原因的. 首先我們來看怎麼在 Ma ...
- VC++ error C2248: “CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)
在使用诸如:CArray或是 CList等类时,经常会出现此错误 此错误的原因是由于自定义的类的数组项时 有一个操作如 Add() 在这个操作中,实际上需要一个 = 操作,但是这个 =操作在 自定 ...
- 《On Lisp》第四章第三节图4.3中的prune函数fix
这个函数作者的原意是删除表中test位真的部分,并且表按原样返回. 作者给出的的测试用例如下: (prune #'evenp '(1 2 (3 (4 5) 6) 7 8 (9))) 返回结果是: (1 ...
- spring整合freemarker
一.配置maven <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...
- Slyx_SerAddGet
##通道##119.29.192.206:12002## ##通道##58.221.49.24:12002##
- JcClient Ip Get
##通道##123.207.157.82:18425## ##通道##112.95.251.214:18425## ##通道##110.52.233.5:18425## ##通道##119.29.19 ...
- 打出10的n次方,上标,下标等处理方法(mac)
我使用mac系统遇到的需求,需要在项目中显示10的6次方 用来做单位,找了很多方案,word等文本编辑工具很好实现(word是使用ctrl + shift + =)(mac 版的word是 Comm ...