a++与++a,谈谈C++的参数传递
先看一段代码:
#include<iostream>
using namespace std;
void func(int a, int b)
{
cout << a << " " << b << endl;
}
int main()
{
int a = 0;
func(a++, ++a);
return 0;
}
由于C++是从右向左入栈(与编译器的调用约定有关,不是C++标准的规定),所以刚看到代码的时候,我以为结果会是“1 1”(先将++a入栈,再将a++入栈),然而事实是: 。这是在VS上面运行的,在g++上也是一样的结果。幸好VS还可以查看汇编代码。
由于在VS上有十分方便的反汇编工具,所以接下来说的东西都基于VS2019自带的反汇编。
设置断点并调试,便可以打开反汇编窗口:
下面这段就是在调用func函数时的汇编代码:
mov eax,dword ptr [a]
add eax,1
mov dword ptr [a],eax //这三行指令将a+1
mov ecx,dword ptr [a]
mov dword ptr [ebp-0D0h],ecx //这两行指令将a的值存储到一个临时地址(寄存器间接寻址)中
mov edx,dword ptr [a]
add edx,1
mov dword ptr [a],edx /这三行指令又将a+1
mov eax,dword ptr [a]
push eax //这两行指令将a压入栈
mov ecx,dword ptr [ebp-0D0h]
push ecx //这两行指令将刚刚存储的临时地址的值压入栈
call func (0A312E9h) //调用func函数
add esp,8 //esp为栈指针寄存器
如果将代码改成
func(++a, ++a);
会是什么结果呢?答案是
mov eax,dword ptr [a]
add eax,1
mov dword ptr [a],eax //这三行指令将a+1
mov ecx,dword ptr [a]
add ecx,1
mov dword ptr [a],ecx //这三行指令将a+1
mov edx,dword ptr [a]
push edx //这两行指令将a压入栈
mov eax,dword ptr [a]
push eax //这两行指令将a压入栈
call func (09912E9h)
add esp,8
可以看到,将a++改成++a之后,指令少了将a的值保存起来的步骤,并且由于并非在读取参数时就压入栈,而是在所有参数的表达式执行完之后才压入,所以最后压入参数栈的都是最后的变量a。
那么结合汇编代码就不难理解文章开头为什么是“1 2”了,基本就是这样的区别(注意:读取参数和执行参数的表达式时也是从右往左的):
在调用函数的时候,参数要避免使用自增和自减,避免出现混乱。
文章为作者结合个人理解编写,可能会有错漏的地方,如有错误,敬请指正。
a++与++a,谈谈C++的参数传递的更多相关文章
- 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针
参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...
- 漫谈C指针:参数传递的三道题目
漫谈C指针:参数传递的三道题目 2009-07-02 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?) 考题一,程序代码如下: [c] view plaincopy ...
- C语言的参数传递
一.三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?) 考题一,程序代码如下:void Exchg1(int x, int y){ int tmp; ...
- [转]谈谈关于MVP模式中V-P交互问题
在差不多两年的时间内,我们项目组几十来号人都扑在一个项目上面.这是一个基于微软SCSF(Smart Client Software Factory)的项目,客户端是墨尔本一家事业单位.前两周,我奉命负 ...
- 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。
windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...
- 谈谈Spring中的BeanPostProcessor接口
一.前言 这几天正在复习Spring的相关内容,在了解bean的生命周期的时候,发现其中涉及到一个特殊的接口--BeanPostProcessor接口.由于网上没有找到比较好的博客,所有最后花了好 ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 谈谈一些有趣的CSS题目(十一)-- reset.css 知多少?
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
随机推荐
- java 参数传递、对象、封装
参数传递分为值传递(传值)和引用传递(传地址). 面向对象的三大特征: 1. 封装 2. 继承 3. 多态 封装表现: 1.方法就是一个最基本封装体. 2.类其实也是一个封装体. 封装的好处: 1.提 ...
- 套接字编程简介: IPV4套接字地址结构/ 通用套接字地址结构/ IPV6套接字地址结构/新通用套接字地址结构
IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名,定义在<netinet/in.h>头文件中. struct in_addr { in_addr_t ...
- TCP/IP协议族基本知识
常见的网络拓扑 两台主机通信的过程:应用进程产生消息,经由主机的 TCP/IP 协议栈发送到局域网(LAN),最后经过广域网(目前最大的广域网的因特网)中的网络设备(路由器)传给目的主机所在的局域网( ...
- System.NotSupportedException:“No data is available for encoding 1252. For information on defining a custom encoding
最近搞 .net项目,Dapper连接Mysql时,运行报错: System.NotSupportedException:“No data is available for encoding 1252 ...
- React-HelloWorld
React-HelloWorld 最简单的React示例如下: ReactDOM.render( <h1>Hello,world!</h1>, document.getelem ...
- ubuntu下Java通过JNI调用C
下面看一个实例,如下: public class TestJNI { static { System.loadLibrary("diaoyong"); // 程序在加载时,自动加载 ...
- iptables 限制端口
限制端口 #!/bin/bashiptables -P INPUT ACCEPTiptables -P OUTPUT ACCEPTiptables -Fiptables -P INPUT DROPip ...
- [Web] 深入理解现代浏览器
转载: https://blog.csdn.net/qihoo_tech/article/details/91921777 奇技指南 身为前端,你真正深入理解了浏览器吗? 本文来自公众号奇舞周刊,作者 ...
- 科研黑帮 | Molecular Genetic Anatomy and Risk Profile of Hirschsprung’s Disease
PNAS又来一篇:Gene- and tissue-level interactions in normal gastrointestinal development and Hirschsprung ...
- EF获取当天的数据集合
).DefaultIfEmpty().Count(); 主要是使用了: DbFunctions.DiffDays