精华内容
下载资源
问答
  • 参数传递函数执行之前,所以++a先执行,然后是a+b。 整体大概是: a自增; a的值放到寄存器1(arg1); a+b的值放到寄存器2(arg2); 函数返回值入栈; -------------执行子函数 int b=arg1; ...
    #include <iostream>
    
    using namespace std;
    
    static inline int func(int a,int b){
    	return a+b;
    }
    
    int func1(int a,int b){
    	return a+b;
    }
    
    int main ()
    {
    	int a=1;
    	int b=2;
    	int a1=1;
    	int b1=2;
    	int res=func(a+b,++a);
    	int res1=func1(a1+b1,++a1);
    	cout<<"res:"<<res<<endl;
    	cout<<"res1:"<<res1<<endl;
    	return 0;
    
    }

    参数传递在函数执行之前,所以++a先执行,然后是a+b。

    整体大概是:

    a自增;

    a的值放到寄存器1(arg1);

    a+b的值放到寄存器2(arg2);

    函数返回值入栈;

    -------------执行子函数

    int b=arg1;

    int a=arg2;

    int c=a+b;

    ------------子函数执行结束

    释放子函数中bac的栈空间;

    c的值放到寄存器(arg3);

    int res=arg3;

     

     

     

    展开全文
  • 本文主要探讨C/C++语言函数间参数的传值传地址机制,同时探讨了计算机在调用一个函数时采用什么样的方法来自适应的处理函数中的参数,即函数调用约定.
  • 函数定义、调用参数传递和函数原型 标签(空格分隔): C 双学位高级语言程序设计 C函数 函数定义 返回值类型 函数名(形参) { 语句 return x; } 虽然return可以在函数内出现多次,但是每个函数只能...

    函数定义、调用、参数传递和函数原型

    标签(空格分隔): C 双学位高级语言程序设计 C函数


    1. 函数定义
      返回值类型 函数名(形参)
      {
      语句
      return x;
      }
      虽然return可以在函数内出现多次,但是每个函数只能执行一个return。
      形参的类型定义不必须写,但是写上便于查错,写上是一个好习惯。
    2. 函数调用
      函数被调用的时候,输入的参数就叫实际参数;函数定义时,定义的参数叫形式参数。
      形参和实参的名字可以相同,只有在调用函数时,才会为形参分配空间。
    3. 函数原型声明
      函数在主函数之后,但已被引用时,会默认函数是int型的;如果函数已经被默认定义类型(不一定是int)了,接下来到它定义的地方,就会报错,显示函数已被隐含定义。所以,为防止这种情况,可以做函数原型声明。
        #include <stdio.h>
        int main()
        {
            long fab(int n)
            ...
        }
    
        long fab(int t)
        {
        ...
        }

    就是这样。这样就不会出错了。

    展开全文
  • 本节,我们看看,如何实现C语言中的函数调用,举个具体例子,在完成本节的代码后,我们的解释器功能进一步增强,使得它能解释执行下面的C语言代码: void f() { int a; a = 1; } void main() { f(); }

    具体的代码讲解和调试演示过程,请参看视频:
    用java开发C语言编译器

    本节,我们看看,如何实现C语言中的函数调用,举个具体例子,在完成本节的代码后,我们的解释器功能进一步增强,使得它能解释执行下面的C语言代码:

    void f() {
        int a;
        a = 1;
    }
    
    void main() {
        f();
    }

    我们先看看函数定义的语法表达式:

    EXT_DEF -> OPT_SPECIFIERS FUNCT_DECL COMPOUND_STMT
    FUNCT_DECL -> UNARY LP RP

    对应于函数f的定义 ,其中 OPT_SPECIFIERS 对应的是关键字void, FUNCT_DECL对应的是 f(), 最后COMPOUND_STMT对应的是:
    {
    int a;
    a = 1;
    }

    根据表达式,解释器会构造如下执行树:
    这里写图片描述

    同理,对于main函数,我们也有同样的执行树:
    这里写图片描述

    在主函数main 中,实现了对函数f的调用,函数调用对应的语法如下:
    UNARY -> UNARY LP RP
    NUARY -> NAME

    其中NAME 对应的是被掉函数名 f, LP RP 对应左右括号。

    我们看看构造执行树的代码对此进行的相应改动,CodeTreeBuilder.java:

    public class CodeTreeBuilder {
    
    private String functionName;
        private HashMap<String, ICodeNode> funcMap = new HashMap<String , ICodeNode>();
    
      public ICodeNode buildCodeTree(int production, String text) {
            ICodeNode node = null;
            Symbol symbol = null;
    
            switch (production) {
            ...
    
            case CGrammarInitializer.NewName_LP_RP_TO_FunctDecl:
            case CGrammarInitializer.NewName_LP_VarList_RP_TO_FunctDecl:
                node = ICodeFactory.createICodeNode(CTokenType.FUNCT_DECL);
                node.addChild(codeNodeStack.pop());
                child =  node.getChildren().get(0);
                functionName = (String)child.getAttribute(ICodeKey.TEXT);
                symbol = assignSymbolToNode(node, functionName);
    
                break;
    
            case CGrammarInitializer.NewName_TO_VarDecl:
                //我们暂时不处理变量声明语句
                codeNodeStack.pop();
                break;
    
            case CGrammarInitializer.NAME_TO_NewName:
                node = ICodeFactory.createICodeNode(CTokenType.NEW_NAME);
                node.setAttribute(ICodeKey.TEXT, text);
                break;
    
            case CGrammarInitializer.OptSpecifiers_FunctDecl_CompoundStmt_TO_ExtDef:
                node = ICodeFactory.createICodeNode(CTokenType.EXT_DEF);
                node.addChild(codeNodeStack.pop());
                node.addChild(codeNodeStack.pop());
                funcMap.put(functionName, node);
                break;
        ....
        }
    }

    由于我们现在是基于函数调用来解释C语言代码的,因此,当我们将一个函数的执行树构造出来后,需要把在执行树的头节点加入一个哈希表,表的关键字用的就是函数名,当某个函数被调用时,解释器会从该表中,通过被调用函数的名字,找到该函数对应的执行树的头节点,然后再根据该执行树进行解释执行相应节点,这样,我们就能实现函数调用了。

    我们再看看函数的执行部分,我们根据执行树,增加了若干个Executor,对应于函数定义执行树的头节点,我们增加了ExtDefExecutor,代码如下:

    package backend;
    
    import frontend.CGrammarInitializer;
    
    public class ExtDefExecutor extends BaseExecutor {
    
        @Override
        public Object Execute(ICodeNode root) {
            int production = (Integer)root.getAttribute(ICodeKey.PRODUCTION);
            switch (production) {
            case CGrammarInitializer.OptSpecifiers_FunctDecl_CompoundStmt_TO_ExtDef:
                executeChild(root, 0);
                ICodeNode child = root.getChildren().get(0); 
                String funcName = (String)child.getAttribute(ICodeKey.TEXT);
                root.setAttribute(ICodeKey.TEXT, funcName);
    
                executeChild(root, 1);
                child = root.getChildren().get(1);
                Object returnVal = child.getAttribute(ICodeKey.VALUE);
                if (returnVal != null) {
                    root.setAttribute(ICodeKey.VALUE, returnVal);
                }
    
    
                break;
            }
            return root;
        }
    
    }
    

    它的逻辑简单,由于它先执行FUNCT_DECL节点,然后在执行函数体,也就是大括号包住的部分。

    我们再看看FUNCT_DECL节点对应的Executor:

    public class FunctDeclExecutor extends BaseExecutor {
    
        @Override
        public Object Execute(ICodeNode root) {
            int production = (Integer)root.getAttribute(ICodeKey.PRODUCTION);
            switch (production) {
            case CGrammarInitializer.NewName_LP_RP_TO_FunctDecl:
                root.reverseChildren();
                copyChild(root, root.getChildren().get(0));
                break;
            }
            return root;
        }
    
    }
    

    该节点执行时,只是单纯的拷贝子节点信息,后面我们实现由参数传递的函数调用时,该节点将发挥重要作用。

    由于函数调用对应的语法是:
    UNARY -> UNARY LP RP
    因此,UnaryExecutor也要做相应改动,代码如下:

    public class UnaryNodeExecutor extends BaseExecutor{
    
        @Override
        public Object Execute(ICodeNode root) {
            executeChildren(root);
    
            int production = (Integer)root.getAttribute(ICodeKey.PRODUCTION); 
            String text ;
            Symbol symbol;
            Object value;
            ICodeNode child;
    
            switch (production) {
            ...
              case CGrammarInitializer.Unary_LP_RP_TO_Unary:
                //先获得函数名
                String funcName = (String)root.getChildren().get(0).getAttribute(ICodeKey.TEXT);
                //找到函数执行树头节点
                ICodeNode func = CodeTreeBuilder.getCodeTreeBuilder().getFunctionNodeByName(funcName);
                if (func != null) {
                    Executor executor = ExecutorFactory.getExecutorFactory().getExecutor(func);
                    executor.Execute(func);
                }
                break;
            ...
            }

    它首先找到要调用的函数名,利用函数名在函数哈希表中找到对应的执行树的头节点,根据头结点构造函数的执行节点ExtDefExecutor,然后调用该Executor的execute接口,于是ExtDefExecutor便开始变量函数f的执行树,在对应节点执行相应操作,从而实现函数f被调用的效果。

    具体的代码讲解和调试演示请参看视频。

    更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
    这里写图片描述

    展开全文
  • arguments在函数中,指向一个类数组,类数组中存放着本次函数调用传递参数,使用arguments可以获取函数的不定参数; function sum() { var sum = 0; for (var i = 0; i < arguments.length; i++) { sum ...

    arguments 在函数中,指向一个类数组,类数组中存放着本次函数调用时传递的参数,使用arguments可以获取函数的不定参数;

        function sum() {
            var sum = 0;
            for (var i = 0; i < arguments.length; i++) {
                sum += arguments[i];
            }
            return sum;
        }
        console.log(sum(1, 2, 3, 4, 5));

    当一个函数的参数非常多的时候,如果每个参数都单独写成一个形参,那么调用会非常麻烦,可以考虑给这个参数封装成一个对象之后在去调用;

        function People(obj) {
            this.name = obj.name;
            this.height = obj.height;
        }

    传递的参数也是对象

        var p1 = new People({
            height: 100,
            name: "张三"
        });

     

    展开全文
  • 参数传递 ...function box(sum,num3) //把函数本身作为参数传递,而不是函数的返回值 { return sum(num3); }function sum(num1) { return num1+11; } var result=box(sum,10) //将函数sum作为参数传递
  • 函数的调用和参数传递 在定义了一个函数之后,只有调用该函数才能执行函数的功能,否则。函数在程序中只是一段静态的代码,而永远不可能执行。 1.函数调用过程 函数调用的一般形式如下 : 如果是无参函数,没有实参表...
  • Python提供了许多内建函数,我们也可以自己创建函数,函数调用参数传递时有几点值得注意。工具/原料电脑python注意事项:1必备参数须以正确的顺序传入函数,调用时的数量必须声明时的一样,不然会出现语法错误。2...
  • Matlab的函数调用和参数传递

    万次阅读 2016-07-03 20:32:27
    函数调用 ...1. 函数调用的时候,参数顺序应该与定义的时候一样。 2. 函数可以嵌套 3. 函数可以自己调用自己,实现递归例如: 1)函数文件: power.m function [out1, out2] = power(in1, in2,
  • 函数调用参数传递

    2016-11-30 13:42:50
    定义 实参 actual parameters,全称为“实际参数”,是在调用传递给函数的参数,即传递给被...formal parameters,全称为“形式参数”,是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传递的参
  • MFC——子窗口之间传递参数和调用函数 这几天在用MFC做ui的时候遇到一个看起来很简单的问题,但是折腾了好久,最后在同门老师的帮助下解决了这个问题,对MFC有了更深的理解,特此记录一下。 一、功能简介 实现...
  • X86  X86在调用函数的时候参数传递
  • 从汇编的角度理解程序 —— 函数调用 我们已经知道,程序是按顺序执行的指令流水线 (PipeLine)。分支循环逻辑,可以通过在流水线中往后跳或往前跳实现。 其实,函数调用也不过是在跳转。调用某个函数,就跳转到...
  • 函数调用时,编译器如何处理形参变量实参变量 当发生函数调用时,需要给形参分配内存,形参变量是实参变量的副本, 在函数调用过程中是形参变量参与整个过程的变化 1. 值传递 void swap(int a, int b) {  int ...
  • 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用 函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时,使用函数可以提高编写的...
  • 常量参数和函数调用

    2020-03-22 07:49:06
    常量参数是普通参数的一种,但是在函数调用中,地址或地址指向的值,或者两者,可以加const,那么在函数调用中就不会改变你不想改变的东西。举例如下: void function(const charp,int n) 大家都知道,在变元传递时...
  • C++函数调用过程深入分析 0. 引言  函数调用的过程实际上也就是一个中断的过程,那么C++中到底是怎样实现一个函数的调用的呢?...本文将对函数调用的过程进行深入的分析详细解释,并在VC 6.0环境下进行演
  • python函数调用参数传递方式 C/C++参数传递方式 对于C程序员来说,我们都知道C在函数调用时,采用的是值传递,即形参实参分配不同的内存地址,在调用时将实参的值传给实参,在这种情况下,在函数内修改形参并...
  • js中this的指向问题 javascript中的this指向 setTimeout 方法带参数传递 setTimeout 调用带参数的函数的方法 如何向回调函数中传入其他参数? 如何向回调函数中传参数 javascript 中怎么给回调函数传值 ...
  • 调用函数时,大多数情况下主调函数和被调函数之间存在着数据传递关系。于是就用到了形式参数和实际参数,简称形参实参。在定义函数函数名后面括号中的变量称为“形参”,在主调函数(一般为Main)调用一个函数...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,005
精华内容 4,802
关键字:

参数传递和函数调用