从汇编看c++函数的默认参数的使用说明

在c++中,可以为函数提供默认参数,这样,在调用函数的时候,如果不提供参数,编译器将为函数提供参数的默认值。下面从汇编看其原理。

下面是c++源码:


代码如下:

int add(int a = 1, int b = 2) {//参数a b有默认值
    return a + b;
}
int main() {
   int c= add();//不提供参数

}

下面是mian函数里面的汇编码:


代码如下:

; 4    : int main() {

push    ebp
    mov    ebp, esp
    push    ecx;为局部变量c分配了4字节的存储空间 ecx为32位寄存器

; 5    :    int c= add();

push    2;将2压栈,就是add函数中b参数的默认值 这里参数压栈方向是从右向左
    push    1;将1压栈,就是add函数中a参数的默认值
    call    ?add@@YAHHH@Z                ; 调用add函数
    add    esp, 8;释放刚才为add提供参数时的储存空间
    mov    DWORD PTR _c$[ebp], eax;eax寄存器里面存放add函数返回值,写入变量c里面

; 6    :   
; 7    : }

xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

下面是add函数的汇编码:


代码如下:

?add@@YAHHH@Z PROC                    ; add

; 1    : int add(int a = 1, int b = 2) {

push    ebp
    mov    ebp, esp

; 2    :     return a + b;

mov    eax, DWORD PTR _a$[ebp];将参数a的值写入寄存器eax
    add    eax, DWORD PTR _b$[ebp];将参数b的值取出与eax里面的值相加,结果存入eax寄存器

; 3    : }

pop    ebp
    ret    0
?add@@YAHHH@Z ENDP

下面是只提供一个参数值得情况

先看c++源码:


代码如下:

int add(int a = 1, int b = 2) {//参数a b有默认值
    return a + b;
}
int main() {
   int a = 3;
   int c= add(a);//只为a提供参数

}

下面是main函数里面的汇编码:


代码如下:

; 4    : int main() {

push    ebp
    mov    ebp, esp
    sub    esp, 8;esp寄存器作为栈指针移动8字节,为局部变量a,c预留存储空间

; 5    :    int a = 3;

mov    DWORD PTR _a$[ebp], 3;将3写入局部变量a所在存储空间

; 6    :    int c= add(a);//不提供参数

push    2;将2压栈,提供b参数默认值
    mov    eax, DWORD PTR _a$[ebp];取出a的值,放入寄存器eax里面
    push    eax;将eax里面的值压栈,提供参数a的值,这里不是提供的默认值1
    call    ?add@@YAHHH@Z                ; 调用add函数
    add    esp, 8;释放刚才为调用函数add为参数分配的8byte空间
    mov    DWORD PTR _c$[ebp], eax;eax里面存放调用函数的结果,写到c所在存储空间里面

; 7    :   
; 8    : }

xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

可以看到,和上面的不同之处在于没有为a提供默认的参数值。

下面是add函数的汇编码,与第一种情况一样,没有变化:


代码如下:

?add@@YAHHH@Z PROC                    ; add

; 1    : int add(int a = 1, int b = 2) {//参数a b有默认值

push    ebp
    mov    ebp, esp

; 2    :     return a + b;

mov    eax, DWORD PTR _a$[ebp]
    add    eax, DWORD PTR _b$[ebp]

; 3    : }

pop    ebp
    ret    0
?add@@YAHHH@Z ENDP

这里由于为参数a给出了明确的值,因此编译器只为参数b提供默认值。可想而知,若为add函数都提供了明确的参数值,那么编译器就不会为参数a,b提供默认值了。

(0)

相关推荐

  • C++中函数的默认参数详细解析

    使用方法:(1)在函数声明或定义时,直接对参数赋值,该参数就是默认参数.(2)在函数调用时,省略部分或全部参数,这时就会使用默认参数进行代替. 注意事项:(1)一般在声明函数是设置默认参数. 如果在函数声明和定义函数时都设置了默认参数,则以函数声明的默认参数为准. 复制代码 代码如下: #include<iostream>using namespace std;int main(){ double add(double a=3.2,double b=9.6);//在函数声明时设置默认参数 co

  • php指定函数参数默认值示例代码

    例1 复制代码 代码如下: <html><head><title>php函数指定默认值-www.jb51.net</title></head><body><?phpfunction printMe($param = NULL){   print $param;}printMe("This is test");printMe();?> </body></html> 输出结果:Thi

  • js函数参数设置默认值的一种变通实现方法

    php有个很方便的用法是在定义函数时可以直接给参数设默认值,如: 复制代码 代码如下: function simue ($a=1,$b=2){ return $a+$b; } echo simue(); //输出3 echo simue(10); //输出12 echo simue(10,20); //输出30 但js却不能这么定义,如果写function simue(a=1,b=2){}会提示缺少对象. js函数中有个储存参数的数组arguments ,所有函数获得的参数会被编译器挨个保存到这

  • ECMAScript6函数默认参数

    语言更新时每一个新增的特性都是从千百万开发者需求里提取过来的,规范采用后能减少程序员的痛苦,带来便捷. 我们经常会这么写 function calc(x, y) { x = x || 0; y = y || 0; // to do with x, y // return x/y } 简单说就是x,y提供了一个默认值为0,不传时x, y以值0来运算.传了就以实际值计算. 又如定义一个ajax function ajax(url, async, dataType) { async = async !

  • php定义一个参数带有默认值的函数实例分析

    本文实例分析了php定义一个参数带有默认值的函数用法.分享给大家供大家参考.具体分析如下: php的函数参数可以指定默认值,指定默认值后,调用时如果不给该参数赋值,则该参数就使用默认值 <?php function capitalize( $str, $each=TRUE ) { $str = strtolower($str); if ($each === TRUE) { $str = ucwords ($str); } else { $str = strtoupper($str); } ech

  • C++函数参数取默认值的深入详解

    一般情况下,在函数调用时形参从实参那里取得值,因此实参的个数应与形参相同.有时多次调用同一函数时用同样的实参,C++提供简单的处理办法,给形参一个默认值,这样形参就不必一定要从实参取值了.如有一函数声明float area(float r=6.5);指定r的默认值为6.5,如果在调用此函数时,确认r的值为6.5,则可以不必给出实参的值,如area( );  //相当于area(6.5);如果不想使形参取此默认值,则通过实参另行给出.如area(7.5); //形参得到的值为7.5,而不是6.5这

  • 详细介绍Python函数中的默认参数

    import datetime as dt def log_time(message, time=None): if time is None: time=dt.datetime.now() print("{0}: {1}".format(time.isoformat(), message)) 最近我在一段Python代码中发现了一个因为错误的使用默认参数而产生的非常恶心的bug.如果您已经知道关于默认参数的全部内容了,只是想嘲笑一下我这可笑的错误,请直接跳到本文末尾.哎,这段代码是我

  • 深入讨论Python函数的参数的默认值所引发的问题的原因

    本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 陷阱重现 我们就用实际的举例来演示我们今天所要讨论的主要内容. 下面一段代码定义了一个名为 generate_new_list_with 的函数.该函数的本意是在每次调用时都新建一个包含有给定 element 值的list.而实际运行结果如下: Python 2.7.9 (default, Dec 19 2014, 06:05:48) [GCC 4.2.1 Compatible Apple LLV

  • 从汇编看c++函数的默认参数的使用说明

    在c++中,可以为函数提供默认参数,这样,在调用函数的时候,如果不提供参数,编译器将为函数提供参数的默认值.下面从汇编看其原理. 下面是c++源码: 复制代码 代码如下: int add(int a = 1, int b = 2) {//参数a b有默认值    return a + b;}int main() {   int c= add();//不提供参数 } 下面是mian函数里面的汇编码: 复制代码 代码如下: ; 4    : int main() { push    ebp    m

  • Kotlin学习教程之函数的默认参数

    前言 ​ 在Java中,为函数的参数添加默认值是不被允许的,这是为了防止默认参数与函数重载同时使用时二义性的问题,考虑下面的例子: void func(p1: String, p2: String, p3: String = "default") { // do something } void func(String p1, String p2) { // do something } 假设上面的代码是可以编译通过的,那么当调用func("p1","p2

  • 通过汇编看golang函数的多返回值问题

    golang这门语言,有个比较好的特性,就是支持函数的多返回值.想C,C++,Java等这些语言,是不支持函数多返回的.但是C,C++可以使用传递指针,实现函数多返回.但是,你有没有想过,golang是怎样实现函数多返回值的呢? 我们知道,C,C++是通过寄存器实现函数返回值的,也就是先把返回值写入到一个寄存器中,然后再从寄存器中,读到函数的返回值.golang也是这样实现的吗? 伟大的思想家孔子曾说过,在源码面前一切都如同裸奔.后来,鲁迅先生,总结了孔子的思想,说出了,在汇编面前,一切语法都是

  • python函数的默认参数请勿定义可变类型详解

    目录 函数的默认参数请勿定义可变类型 可变类型和不可变类型 定义可变类型会有什么问题? 导致的原因 解决方法 关于可变类型作为默认参数时的注意点 测试:将可变类型列表换为字典 测试:来个不可变类型字符串 测试:元祖包个列表来 小结一下 函数的默认参数请勿定义可变类型 经常会看到这样一句代码警告: Default argument value is mutable 意思是告诉我们函数的定义中,使用可变类型做默认参数. 那为什么会有这个警告呢? 可变类型和不可变类型 可变类型(mutable):列表

  • Python中函数及默认参数的定义与调用操作实例分析

    本文实例讲述了Python中函数及默认参数的定义与调用操作.分享给大家供大家参考,具体如下: #coding=utf8 ''''' Python中的函数使用小括号调用.函数在调用之前必须先定义. 如果函数中没有return语句,就会自动返回None对象. Python是通过引用调用的.如果函数内对参数的改变会影响到原始对象. 只有可变对象会受此影响,对不可变对象,它的行为类似按值调用. ''' ''''' 定义函数: def function_name([arguments]): "option

  • 深入解析C++中的函数模板和函数的默认参数

    C++函数模板 我们知道,数据或数值可以通过函数参数传递,在函数定义时它们是未知的,只有在发生函数调用时才能确定其值.这就是数据的参数化. 其实,数据类型也可以通过参数来传递,在函数定义是可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的参数自动确定数据类型.这就是数据类型参数化. 所谓函数模板,实际上是建立一个通用函数,其返回值类型和形参类型不具体指定,用一个虚拟的类型来代替(实际上是用一个标识符来占位).这个通用函数就称为函数模板(Function Template).凡是函数

  • Python函数的默认参数设计示例详解

    在Python教程里,针对默认参数,给了一个"重要警告"的例子: def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3)) 默认值只会执行一次,也没说原因.会打印出结果: [1] [1, 2] [1, 2, 3] 因为学的第一门语言是Ruby,所以感觉有些奇怪. 但肯定的是方法f一定储存了变量L. 准备知识:指针 p指向不可变对象,比如数字.则相当于p指针指向了不同的内存地址. p指向的是可变对象,

  • C++函数的默认参数详情

    文章转自微信 公众号:Coder梁(ID:Coder_LT) C++当中的支持默认参数,如果你学过Python,那么想必对此不会陌生.C++中的默认参数的用法和Python基本一致. 使用默认参数的方法非常简单,也就是我们在函数声明的时候,就为某些参数指定好默认值.当我们调用函数的时候,如果没有传入对应的参数,那么则使用默认值. 比如: void func(int a, int b=2, int c=3, int d=4) { cout << a << " "

  • 解析C++函数的默认参数和占位参数及较之C语言的拓展

    可以将占位参数与默认参数结合起来使用 意义: 为以后程序的扩展留下线索 兼容C语言程序中可能出现的不规范写法 //C++可以声明占位符参数,占位符参数一般用于程序扩展和对C代码的兼容 int func(int a, int b, int = 0) { return a + b; } void main() { //如果默认参数和占位参数在一起,都能调用起来 func(1, 2); func(1, 2, 3); system("pause"); } 默认参数对C的函数拓展 1.C++中可

随机推荐