精华内容
下载资源
问答
  • C语言基础知识:C语言函数调用怎么返回两个值

    万次阅读 多人点赞 2018-09-22 11:45:29
    在C语言中,函数只能返回一个值,要返回两个值,可以改换思路,通过其它方式做到。 1 建立数组,返回指针。 在要返回的两个值类型相同时,可以用创建数组的方式,将要返回的值存在数组中,并返回数组首地址,这样...

    在C语言中,函数只能返回一个值,要返回两个值,可以改换思路,通过其它方式做到。

    1 建立数组,返回数组首地址(指针)。

    在要返回的两个值类型相同时,可以用创建数组的方式,将要返回的值存在数组中,并返回数组首地址,这样就可以实现返回两个值的效果。
    需要注意的是,要返回数组首地址,那么返回的值不可以是局部变量,有如下几种是可以的:
    a) 使用静态局部变量存储,并返回地址;
    b) 使用全局变量存储,返回地址;
    c) 函数中动态分配内存,并返回申请到的地址,此种方法需要注意,在使用后需要释放;
    d) 在参数中传入数组地址,并返回。即返回的实际上是主调函数中的变量地址。

    2 建立结构体,返回结构体指针/结构体变量。

    将需要返回的值,写成结构体形式,并返回结构体变量或返回结构体指针,这样可以实现一个返回值中含有多组数据。

    3 当数据规模较小时,可以采用将小规模数据合并为大规模数据的方式,进行返回。

    比如,需要返回两个char型数据时,可以通过返回一个short数据,高地位分别存储各自的值。

    4 输出型参数返回

    还可以不使用返回值的方式,而是通过函数参数传值,如使用输出型参数,举个例子:对于strcpy函数原型:

    char *strcpy(char *strDest,const char *strSrc)

    解析:strDest为输出型参数。

    输出型参数与输入形参数解析:一般不带const的是输出型参数,使用const修饰的是输入形参数,如strSrc

    5 使用全局变量

     

    展开全文
  • 第二函数返回局部变量问题函数是可以返回局部变量的,比如看下面代码就是对的int fun() { int a = 9; return a; }int main () { printf("%d", fun()); return 0; }程序的运行过程是依照栈的规则,函数开始...

    第二个坑 函数返回局部变量问题

    函数是可以返回局部变量的,比如看下面代码就是对的

    int fun()
    {
        int a = 9;
        return a;
    }
    
    int main ()
    {
        printf("%d", fun());
        return 0;
    }

    程序的运行过程是依照栈的规则,函数开始调用就是压栈,函数调用结束就是弹栈。函数弹栈之后该函数占用的内存自然就被释放掉了(重点是……栈)。我们返回的局部变量实际上已经不是局部变量本身了,而是它的复制品。系统会创建一个临时变量来拷贝被return的变量的值。
    因此上面的代码是正确的。那么我们来看下面的代码

    char* fun()
    {
        char a[128];
        sprintf(a, "c语言的那些坑");
        return a;
    }
    
    int main ()
    {
        printf("%s", fun());
        return 0;
    }

    这段代码就是错误的,假设程序照常运行,会出现什么情况。函数fun()返回了a之后,会将a的值拷贝到临时变量。注意是将a的值拷贝到临时变量,而不是拷贝a指向的那块内存里的值。a是什么,a是局部变量数组a的首地址。而a所指的值他的生命周期在函数fun运行结束时就已经停止。内存被销毁。主调函数得到的指针指向的区域已经被销毁,因此是错误的。
    继续看下面这段代码

    char* fun()
    {
        char *a;
        a = "c语言的那些坑";
        return a;
    }
    
    int main ()
    {
        printf("%s", fun());
        return 0;
    }

    还按照刚才的逻辑分析,主调函数可以得到a的值,a的值是什么,a的值是“C语言的那些坑”这个字符串所在的地址。我们强调过,函数调用结束后,函数的栈内存都会被释放掉。注意我说的是栈。而“C语言的那些坑”这个字符串没有存放在栈内。因此,被调函数结束调用时,不会释放掉这个字符串所在的内存。所以主调函数拿到了指针之后,可以得到指针指向的内存的内容。

    大概总结一下,函数返回局部变量是被允许的。只是在返回指针变量的时候,我们需注意,在程序跳出这个函数后这个指针所指的内容是否依旧存在。判断指针所指内容是否依旧存在,这就要求我们对程序运行过程中内存的分配规则有一定的了解。具体内容可以百度一下“内存四区模型”。我们这里只告诉大家我们容易犯的错误。
    看下面代码

    char* fun_1()
    {
        char *a = "c语言的那些坑";
        return a;
    }
    
    char* fun_2()
    {
        char a[] = "c语言的那些坑";
        return a;
    }

    这两个函数看似类似,使用方法也类似,但本质不同,所以结果不同。fun_1是创建一个指针,指针指向了常量区的字符串。函数调用结束后,主调函数得到指针值,依旧可以访问指向的内存。fun_2 是创建了一个数组,数组的内容是那个字符串。这个数组是在栈上存储的,当函数调用结束后,栈内存被回收。所以主调函数得到的指针指向了一个已经被回收的地方,因此fun_2是错误的。

    展开全文
  • 交换两个变量的,容易联想到【两量交换借助中间变量】的方法。 若用函数调用的方式来实现交换,沿用上述思路初步实现如下: #include<stdio.h> void exchange(int,int); void exchange(int one,...

    交换两个变量的值,容易联想到【两量交换借助中间变量】的方法。

    若用函数调用的方式来实现交换,沿用上述思路初步实现如下:

    #include<stdio.h>
    void exchange(int,int);
    void exchange(int one,int another){
        int t;
        t = one;
        one = another;
        another = t;
    }
    int main(){
        int num1;
        int num2;
        printf("输入需要交换的两个数:\n");
        scanf("%d %d",&num1,&num2);
        exchange(num1,num2);
        printf("交换后的两个数为:%d %d\n",num1,num2);
        return 0;
    }
    

    结果说明,未能完成交换。

    回看上述程序实现的方式,涉及到了函数传递中至关重要的问题—实参和形参之间的关系。

    notes

    1.形参: formal argument,形式参数

    它是被调函数中的局部变量,每当调用函数时,这些变量就会被赋值。它只在被调用时才会被分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。

    2.实参: actual argument

    它是调用函数分配给被调函数变量的特定数值,可以是常量/变量或一个表达式。执行时,首先要计算其值,然后将该值复制一份给被调函数中相应的形参。

    既然被调函数使用的值是从调用函数中复制而来的,所以不管在被调函数中对复制的数值进行什么操作,调用函数中的原数值不会受到任何影响。

    这好比原件和复印件之间的关系:在复印件上做的任何改动都不会对原文件造成丝毫影响。

    因此,上述程序中,num1和num2虽然成功把值传给了one、another,one、another也完成了它们之间数值的交换,但是也仅仅是one、another之间交换了,和num1和num2本身没有关系。

    这是一次单向的值传递过程,函数exchange的实参能传给形参,但形参-one、another是定义在函数exchange中的局部变量,当函数调用结束后,它俩就会被释放,因此它们没有渠道把交换的值传回给需要交换的num1,num2。

    既然想要通过函数调用的方式来解决这个问题,先来了解函数调用的具体实现过程。

    首先,各个函数都有一定的堆栈空间。函数形参和实参的传递需要依赖系统堆栈来实现

    【堆栈基础知识】

    • 栈:由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
    • 堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收
    • 在堆栈中变量分布是从高地址到低地址分布

    现在继续来看函数调用的过程.

    step1:

    >--主函数调用子函数,实参入栈。(若实参为表达式,则从右向左依次的将实参表达式的值计算出来)

    按本文一开始提到的例子来说,即就是num1和num2入栈,而实参num1,num2在系统堆栈中所占用的空间,就是与之对应的形参变量的空间。

    这意味着已经完成了"参数传递":

    num1的地址赋值给了one所指向的空间—> * one = &num1;

    num2的地址赋值给了another所指向的空间—> * another= &num2;

    step2:

    >-- 通过call汇编指令,调用子函数,将eip入栈,再通过ret指令出栈,并赋值给eip,从而保证函数调用及返回顺序的正常。

    由于函数调用的时候是汇编中的地址的跳转,而在汇编中的跳转源于标号地址IP。

    所以这里就要涉及到汇编相关的知识

    【note】

    • eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

    • esp:寄存器存放当前线程的栈顶指针

    • ebp:寄存器存放当前线程的栈底指针

    ESP指向栈顶,程序执行时移动,ESP减小分配空间,ESP增大释放空间,ESP又称为栈指针。

    call指令的执行过程大致如下:

    1) call指令首先将主调函数在子函数返回后要执行的下一条指令的地址入栈(返回地址此时在栈顶),然后,更改eip的值,以开始执行子函数的第一条指令,从而开启子函数的执行。

    2) 当子函数运行结束后,执行ret指令,这将导致处在栈顶的返回地址出栈,并更改eip的值,返回主调函数下一条指令。

    step3:

    >--编译器将栈底指针移动到栈顶位置,再将堆栈当前栈底向上的空间分配给子函数的局部变量

    step4:

    >-- 子函数运行结束后,恢复到以前的栈底和栈顶指针。栈顶指针再减去形参变量所占用的空间,恢复到子函数调用之前的状态。

    现在再来解决最初的问题:利用函数调用来实现两个变量的交换:

    #include<stdio.h>
    void Exchange(int *one, int *another);
    void Exchange(int *one, int *another){
        int temp;
        temp = *one;
        *one = *another;
        *another = temp;
    }
    void main(void){
        int num1;
        int num2;
        printf("输入两个需要交换的数\n",num1,num2);
        scanf("%d %d",&num1,&num2);
        Exchange(&num1,&num2);//实参类型为首地址
        printf("交换完毕后两个数的值为%d和%d\n",num1,num2);
    }
    
    
    
    

    运行结果:

    展开全文
  • 1>子函数返回局部变量 例子1: 上面的简单程序,大家应该都知道应该会输出什么。是的,输出如下图: 引出的思考:子函数doubletimes()中的返回变量k是局部变量,返回到主函数后该变量超出了作用域,已经...

    1>子函数返回局部变量

    例子1:


    上面的简单程序,大家应该都知道应该会输出什么。是的,输出如下图:


    引出的思考:子函数doubletimes()中的返回变量k是局部变量,返回到主函数后该变量超出了作用域,已经被销毁了,为什么主函数中的变量m还会等于20呢?

    引出的结论:C语言中参数的传递(包括输入参数和返回参数)实质上都是传递的参数的拷贝。

    在上面例子中,子函数返回值k=20,实际返回的不是变量k,而是会将变量k复制一份,返回副本。

    2> 子函数返回局部指针

    指针也是变量,只不过指针变量的值表示的是内存中的地址而已。所以例子1引出的结论在这里也适合指针变量

    例子2:


    虽然在子函数doubletimes()中返回的指针变量n在return后会“销毁”,但是它的副本会被返回到main()函数中,并赋值给指针变量k。

    输出结果如下图:


    k比n大4的原因是,上例中的变量是int类型的,我的编译环境决定了int类型占4个字节。

    3> 通过子函数修改main函数的变量

    例子3:


    通过例子1,想一下上面例子会返回什么呢??

    由于 参数传递只是副本的传递,那么传进子函数doubletimes()中的变量n不是main函数中的变量n,而是其副本。在子函数中修改副本的值,对main函数中的变量n是没有影响的。返回值如下图:


    那么该如何在子函数中修改main函数中的变量呢??

    例子4:


    记住两点:指针也是变量;通过指针变量能间接访问其他变量并修改其值。

    例4中的内存示意图如下图:


    由上图可知:在子函数中也可返回main函数中的变量n,并可修改其值。程序出如下图:





    4>通过子函数修改main()函数中指针变量

    指针变量的值即指针所指向变量的地址。


    例4的内存结构图如下图:


    在子函数中可间接访问main函数中的指针变量n,从而改变其值,也就改变了指针n的指向了。

    输出结果如下图:


    总结:

    想要在子函数中修改main函数中变量的值,需要传更高一级的变量到子函数。例如,改变普通变量的值,需要传一级指针;改变一级指针的值需要传二级指针等等。


    展开全文
  • 函数返回局部变量string的时候能不能被引用? 前天被同事突然问道这问题,见到string一时糊涂了,最初学习C++的时候,就说不能引用局部变量,现在怎么糊涂了呢?呵呵   今天想了下,原来是被函数外表蒙蔽了,看...
  • C++中全局函数和局部函数的关系

    千次阅读 2017-12-09 17:10:00
    #include using namespace std; //面向对象的模型-全局函数成员函数class Test { public: int a; int b; public: Test(int a=0,int b=0) { this->a = a; this->b = b; } Test T
  • 解决c++中函数返回参数

    千次阅读 2018-12-02 16:16:56
    一个函数只能返回个值,然而有时候函数需要同时返回个值,使用引用形参为我们一次返回多个结果提供了有效的途径。   比如我们想要实现对一个数组进行操作,并且返回经过处理后的数组,这时就可以使用引用来...
  • C++函数返回局部变量指针的问题

    千次阅读 2015-11-08 16:48:34
    讲这问题之前要先简单讲一下C++的内存管理。 更详细的内容可以参考这篇文章《C++内存管理》。 C++程序的内存被分为堆(heap),栈(stack),全局/静态存储区,自由存储区和常量存储区。 1)堆(heap):new...
  • 如何让一个函数返回返回值

    万次阅读 多人点赞 2018-07-29 20:26:47
    以一题目为例: ...利用结构体,注意函数定义一定要用结构体来定义 struct trans { int chi; int cun; }; trans transform(int); int main() { using namespace std; int a; cin &gt;&gt;...
  • 函数返回结构体的内幕

    万次阅读 2014-11-23 13:08:01
    函数返回结构体的内幕 在刚接触C语言编程时,无论是前辈还是教科书,都反复告诫我们两件事: ①函数的参数是传递(意味着在函数中对参数本身的修改无法“传回”); ②不要返回函数体内局部变量的地址,因为...
  • 函数不能返回局部指针变量

    千次阅读 2012-10-08 01:12:14
    声明自动指针变量时,编译器为其在堆栈区分配内存,如果在函数中将另外一自动...函数返回指针。本来就是一比较容易出问题的操作。在霍顿的《VC++ 入门经典》一书中,给出了一很有代表性的例子,如下: // Ex5_
  • lua函数具有大特征:函数作为第一类函数具有特定的词法域(Lexical Scoping) 所谓第一类:代表函数和其他传统类型的是等价的(例如数字和字符串),函数可以同他们一样存储在变量,table中,可以作为...
  • 1、与经验不符的输出我们知道,当发生以下三种情况之一时,对象对应的类的复制构造函数将会被调用:1)对一对象做显示的初始化操作时2)当对象被当作参数传递给某个函数时3)当函数返回类的对象时所以,当我们...
  • 关于C语言函数返回数组c语言中函数不能直接返回一数组,但是可以用其他方式实现类似功能,不过需要注意:1、该数组不能是返回函数的局部变量数组,因为局部变量数组在退出函数后会被释放。可以是全局变量,...
  • C++函数返回map的种方式的比较

    千次阅读 2017-09-27 16:42:04
    当C++函数涉及到复杂的数据处理时,可以采用下面种不同的传递方法:第一种:将map作为函数的返回值,通过复制的方式,将传递给返回值,开销比较大。第二种:将map的引用作为函数参数传入,计算结果直接反映在...
  • 关于fork()函数两个返回值

    千次阅读 2014-05-10 21:40:25
    对于刚刚接触Unix/Linux操作系统,在Linux下编写多进程的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。  首先我们来看下fork函数的原型: #include #include  pid_t fork(void); ...
  • 求矩阵局部的几最大

    千次阅读 2018-05-23 17:19:55
    对矩阵进行处理的时候,有时候需要求局部最大值,但是matlab中的max()函数只能求最大的一个值,并且无法返回最大值所处的位置,为此,本文利用matlab的find和sort函数实现了求矩阵局部最大值。M = rand(9,9); % ...
  • 作用域在局部范围内(例如函数)的对象。这样的对象可以把对象的引用或者指针存在栈中,随着函数的结束而销毁,而把创建的对象内容存在堆中。如果需要在堆上创建对象,要么使用new运算符,要么使用malloc系列函数。 ...
  • 作者:神奇先生链接:...编程时经常会写的一种函数叫做named constructor,这种函数的返回值是某个类的实例,其实本质上就是一种构造函数,但是因为可能需要在构建时执行一些其他的步骤,所以没有写成con...
  • 在C++函数返回数值的三种方法

    万次阅读 多人点赞 2019-05-28 15:59:56
    预备知识 指针函数 C++ 中指针函数的基本形式: 函数类型 * 函数名 (参数数据...例如下面这个函数就是一指针函数: int * a(int b[], int c){ cout<<"Hello"; return b; } 指针函数的返回值是一指针,...
  • 参考文章链接: http://blog.csdn.net/hlsdbd1990/article/details/45970959 http://blog.csdn.net/misskissc/article/details/10757975 http://bbs.csdn.net/topics/390153974 ...感谢位博主和
  • 关于C语言函数返回数组的问题

    万次阅读 2016-11-29 23:03:52
    关于C语言函数返回数组 c语言中函数不能直接返回一数组,但是可以用其他方式实现类似功能,不过需要注意: 1、该数组不能是返回函数的局部变量数组,因为局部变量数组在退出函数后会被释放。 可以是全局变量,...
  • 1.局部变量的指针和局部指针变量是两个不同概念 2.局部变量在函数体结束后生命期也结束,它的指针(即它的地址)是无效变量的地址,所以函数不能返回这种地址 3,局部指针变量在函数结束后生命期也结束,但它...
  • c++ 函数返回引用

    万次阅读 多人点赞 2010-07-17 15:15:00
    c++ 返回函数引用
  • C++函数返回类型和return语句

    千次阅读 2017-10-28 19:02:48
    定义return语句终止当前正在执行的函数并将控制权返回给调用该函数的地方。return语句有种形式:return; return expression;无返回值的函数没有返回值的return语句只能用在返回类型是void 的函数中,返回void 的...
  • c++函数返回数组

    千次阅读 2013-05-04 21:51:01
    不能返回局部数组,因为它是临时变量,暂存在栈区里面,函数调用结束,数组会被释放。 如果需要返回数组可以用如下3种方法: (1)调用之前先创建数组,将数组的地址也就是指针作为参数传递进函数。 int *GetData...
  • MATLAB自定义函数局部变量

    千次阅读 2014-07-31 10:07:37
    1、编写自定义函数时尽量分以下四部分:(1) 函数定义行:function[out1,out2,..]=filename(in1,in2,..),输入和输出参数个数分别由nargin和nargout两个MATLAB保留的变量来给出。(2) 第一行帮助行,以%开头,作为look...
  • C++函数——返回类型

    千次阅读 2018-07-09 21:50:37
    只要函数返回类型不是void, 则该函数内的每条return语句必须返回个值。     返回个值的方式和初始化一个变量或形参的方式完全一样: 返回的值用于初始化调用点的一个临时量, 该临时量就是函数调用的...
  • 【C++】 函数返回vector

    千次阅读 2020-03-04 15:52:30
    当程序中要返回vector时,一般做法会将函数直接定义为: vector<T> func(){ //TODO } 而为了提高执行效率,可以直接返回该vector的引用...但要注意的是,该要返回的vector不能是函数内部的局部变量。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 322,816
精华内容 129,126
关键字:

局部函数返回两个值