4-01-(C++类 this指针)

news/2025/1/19 14:04:09/文章来源:https://www.cnblogs.com/yuyuyu0key/p/18679540

结构体传参,传递的是副本

结构体里面写函数,结构体的大小不变

函数的地址不在结构体里面。

类里面的函数都要传一个this指针,即

lea         ecx,[s]  

普通的函数结构体传参

this指针的特点

1、你用或者不用,它就在那里
2、参数个数确定的时候,用ecx来传递
3、参数个数不确定的时候,最后一个传递(参见不定长参数)
4、this指针不能做++ -- 等运算,不能重新被赋值.
5、this指针不占用结构体的宽度.

类的函数传参与普通函数的传参

struct st
{int x;int y;st(int x, int y){this->x = x;this->y = y;}int Add(){return this->x + this->y;}int Sub(){return this->x - this->y;}int Mul(){return this->x * this->y;}int Div(){return this->x / this->y;}
};
s.Add();
008F460B 8D 4D F0             lea         ecx,[s]  
008F460E E8 D0 CD FF FF       call        st::Add (08F13E3h)008F2F40 55                   push        ebp  
008F2F41 8B EC                mov         ebp,esp  
008F2F43 81 EC CC 00 00 00    sub         esp,0CCh  
008F2F49 53                   push        ebx  
008F2F4A 56                   push        esi  
008F2F4B 57                   push        edi  
008F2F4C 51                   push        ecx  
008F2F4D 8D 7D F4             lea         edi,[ebp-0Ch]  
008F2F50 B9 03 00 00 00       mov         ecx,3  
008F2F55 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
008F2F5A F3 AB                rep stos    dword ptr es:[edi]  
008F2F5C 59                   pop         ecx  
008F2F5D 89 4D F8             mov         dword ptr [this],ecx  
008F2F60 B9 66 C0 8F 00       mov         ecx,offset _570D0804_main@cpp (08FC066h)  
008F2F65 E8 B6 E3 FF FF       call        @__CheckForDebuggerJustMyCode@4 (08F1320h)  
return this->x + this->y;
008F2F6A 8B 45 F8             mov         eax,dword ptr [this]  
008F2F6D 8B 00                mov         eax,dword ptr [eax]  
008F2F6F 8B 4D F8             mov         ecx,dword ptr [this]  
008F2F72 03 41 04             add         eax,dword ptr [ecx+4]
//ecx就是this指针,指向结构体第一个成员

普通函数

Add(&s);
005052CB 8D 45 F0             lea         eax,[s]  
005052CE 50                   push        eax  
005052CF E8 05 C1 FF FF       call        Add (05013D9h)  
005052D4 83 C4 04             add         esp,4  005017D0 55                   push        ebp  
005017D1 8B EC                mov         ebp,esp  
005017D3 81 EC C0 00 00 00    sub         esp,0C0h  
005017D9 53                   push        ebx  
005017DA 56                   push        esi  
005017DB 57                   push        edi  
005017DC 8B FD                mov         edi,ebp  
005017DE 33 C9                xor         ecx,ecx  
005017E0 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
005017E5 F3 AB                rep stos    dword ptr es:[edi]  
005017E7 B9 66 C0 50 00       mov         ecx,offset _570D0804_main@cpp (050C066h)  
005017EC E8 2F FB FF FF       call        @__CheckForDebuggerJustMyCode@4 (0501320h)  35: 	return s->x + s->y;
005017F1 8B 45 08             mov         eax,dword ptr [s]  
005017F4 8B 00                mov         eax,dword ptr [eax]  
005017F6 8B 4D 08             mov         ecx,dword ptr [s]  
005017F9 03 41 04             add         eax,dword ptr [ecx+4]  36: }
005017FC 5F                   pop         edi  
005017FD 5E                   pop         esi  
005017FE 5B                   pop         ebx  
005017FF 81 C4 C0 00 00 00    add         esp,0C0h  
00501805 3B EC                cmp         ebp,esp  
00501807 E8 38 FA FF FF       call        __RTC_CheckEsp (0501244h)  
0050180C 8B E5                mov         esp,ebp  
0050180E 5D                   pop         ebp  
0050180F C3                   ret  

普通函数外平栈,即调用约定为cdcall

类的函数内平栈,即调用约定为stdcall

空结构体的大小

为一

image-20241201120931944

作业

1、设计一个结构体,有两个Int类型的成员X,Y 在结构体内部定义4个函数							分别实现对X Y的加法、减法、乘法与除法的功能.							2、观察这些函数调用的时候,与其他的函数调用有哪些不同?							从参数传递、压栈顺序、堆栈平衡来总结.							3、空结构体的大小是多少?为什么?							4、下面代码能否执行?						struct Person  						
{  						void Fn_1()						{					printf("Person:Fn_1()\n");				}					void Fn_2() 						{					printf("Person:Fn_2()%x\n");				}					
};  						int main(int argc, char* argv[])						
{						Person* p = NULL;					p->Fn_1();					p->Fn_2();					return 0;					
}						4、下面代码能否执行?						struct Person  						
{  						int x ;					void Fn_1()						{					printf("Person:Fn_1()\n");				}					void Fn_2() 						{					x = 10;				printf("Person:Fn_2()%x\n");				}					
};  						int main(int argc, char* argv[])						
{						Person* p = NULL;					p->Fn_1();					p->Fn_2();					return 0;					
}						
调用成员函数add反汇编
39:       t.add();
00401084 8D 4D F8             lea         ecx,[ebp-8]					*
00401087 E8 79 FF FF FF       call        @ILT+0(St::add) (00401005)00401100 55                   push        ebp
00401101 8B EC                mov         ebp,esp
00401103 83 EC 44             sub         esp,44h
00401106 53                   push        ebx
00401107 56                   push        esi
00401108 57                   push        edi
00401109 51                   push        ecx							*
0040110A 8D 7D BC             lea         edi,[ebp-44h]
0040110D B9 11 00 00 00       mov         ecx,11h
00401112 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401117 F3 AB                rep stos    dword ptr [edi]
00401119 59                   pop         ecx							*
0040111A 89 4D FC             mov         dword ptr [ebp-4],ecx			  *这里将结构体的指针传入函数栈帧中
14:           return this->X+this->Y;
0040111D 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401120 8B 00                mov         eax,dword ptr [eax]
00401122 8B 4D FC             mov         ecx,dword ptr [ebp-4]
00401125 03 41 04             add         eax,dword ptr [ecx+4]
15:       }
00401128 5F                   pop         edi
00401129 5E                   pop         esi
0040112A 5B                   pop         ebx
0040112B 8B E5                mov         esp,ebp
0040112D 5D                   pop         ebp
0040112E C3                   ret

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/871689.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

协议通道版iMessage蓝号检测,iMessages数据筛选,无痕检测是否开启iMessage服务

一、实现iMessage数据检测的两种方式:1.人工筛选,将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。2…

【开源】一款功能全面的商用级溯源防伪系统,适用于各种溯源场景

项目介绍 HiPi是一款开源、功能全面的商用级溯源防伪系统,一物一码系统,适用于各种溯源场景的大、中、小、微规模企业。系统能够追踪记录产品的生命周期各个环节,并将产品信息保存在系统中,实现品牌保护、产品营销、防止假冒伪劣产品、防窜货、产品追踪溯源等功能。 应用场…

行为分析智能监测摄像机

行为分析智能监测摄像机具有高效的行为识别和分类能力。通过摄像头捕捉到目标区域内的行为活动,并通过预先训练好的机器学习算法进行识别和分类,可以准确地分析出不同的行为特征,例如跌倒、打架等,并及时发出警报或提醒相关管理人员。这种高效的行为识别能力可以帮助监控中…

秸秆焚烧自动监测摄像机

秸秆焚烧自动监测摄像机具有高效的监测和识别能力。通过摄像头捕捉到秸秆焚烧的情况,并通过预先训练好的机器学习算法进行识别和分类,可以准确地分析出不同的烟雾、火焰等特征,并及时发出警报或提醒相关管理人员。这种高效的监测和识别能力可以帮助监测中心快速反应异常情况…

ServletContext 的 4 个常见应用!

一、ServletContext类详解 Web容器在启动时,会为每一个Web项目创建一个对应的ServletContext对象。它是当前项目中所有Servlet实例之间信息交互的“中间商”。(参见“Servlet的运行原理”) 注:一个Web项目对应一个ServletContext。(即:同一个Web项目中的所有servlet实例共…

Servlet 映射(访问)路径的 3 种方式!

Servlet的映射(访问)路径是在Web配置文件(web.xml)中编写的。如: <!-- Servlet的访问路径 --> <servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping>1、servlet映射…

Java初学者笔记-05、集合框架

集合体系 集合是可变长的。 Collection:代表单列集合,每个元素包含一个值。 Map:代表双列集合,每个元素包含两个值。 Collection集合List系列集合:添加的元素是有序、可重复、有索引。ArrayList、 LinekdList:有序、可重复、有索引。Set系列集合:添加的元素是无序、不重…

.NET周刊【1月第1期 2025-01-05】

国内文章 3款.NET开源、功能强大的通讯调试工具,效率提升利器! https://www.cnblogs.com/Can-daydayup/p/18631410 本文介绍了三款功能强大的.NET开源通讯调试工具,旨在提高调试效率。这些工具包括LLCOM,提供串口调试和自动化处理功能;Wu.CommTool,支持Modbus RTU和MQTT调…

Servlet 详解!

一、Servlet简介 Servlet是Sun公司开发动态Web的一门技术。Sun公司在这些API中提供了一个Servlet接口,如果你想开发一个Servlet程序只需要完成如下两个步骤: 1、编写一个Java类实现Servlet接口。 2、把开发好的Java类部署到Web服务器中。 我们把实现了Servlet接口的Java程序叫…

图论/连通性

点边连通度:耳分解: 强连通有向图/边双联通无向图 从一个点出发,每次加入从集合出发回到集合,中间点不在集合内的环,一定能生成该图。 边双 强连通 双极定向:link 割空间与环空间互为正交补。 切边等价:模板 qoj1351CF1648F 树分解:也就是找到一种划分方式,使得每种划…

比特c语言-分支与循环

# 分支与循环 if语句 目录if语句ifeg:输入一个整数,判断是否为奇数elseeg:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印偶数嵌套ifeg:输入一个人的年龄关系操作符条件操作符eg:使用条件操作符表示代码逻辑eg:使用条件表达式找两个数中较大值逻辑操作符…