• C语言函数间参数的传递方式(一)有返回的函数


    “我们是伞兵,本来就该被包围的!”----《兄弟连》。

    在战争中,伞兵天生就该被包围,而在编程语言中,函数生来就该被调用。在被调用的过程中,执行函数的指令,完成值和参数的传递。按照不同的传递方式,函数可以分为下面几类:

     

     1、先来看返回变量、常量的函数:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int func(int a)
     5 {
     6     a=2*a*a;
     7     printf("a=%d
    ",a);
     8     return a;
     9 }
    10 int main()
    11 {
    12     int b=func(10);
    13     printf("b=%d
    ",b);
    14     return 0;
    15 }

    上面的函数是返回变量的值,如果把被调函数func中的变量a换成常量,程序依然能够得到正确结果。例如:

     1 #include <stdio.h>
     2 
     3 int func()
     4 {
     5     const char a='W';
     6     printf("A=%c 
    ",a);
     7     return a;
     8 }
     9 int main()
    10 {
    11     char b=func();
    12     printf("b=%c 
    ",b);
    13     return 0;
    14 }

    也许有人会问,辛辛苦苦敲了半天代码,就返回了一个字符,为什么不返回一个字符串那?返回字符串不是不行,可要返回字符串,就不能按照返回一般的变量、常量来处理了。我们知道,在C语言编程环境下,字符串只能用字符型数组或者字符型指针来声明和定义,不存在C++语言语言环境下的string类型。因此,当你要返回字符串的时候,其实需要返回的是字符串的地址。这就引出了我们的下一个课题:

    2、返回字符串地址

    函数不仅能返回值,还能返回地址。返回地址时,需要在函数的返回值数据类型前面加”*“,下面看例程:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 char* getString()
     6 {
     7     char str[] = "hello,world";
     8     return str;                  //返回数组地址
     9 }
    10 void test02()
    11 {
    12     char* p = NULL;
    13     p = getString();  //接收字符串数组地址
    14     printf("test02返回字符串数组:  %s 
    ", p); 
    15     /* 因为p接收的是被返回的字符串数组的地址。而字符串数组在栈上,    当getString函数
    16     执行完以后,str字符串已经被内存释放了,test02函数调用它的结果就不确定了。 */
    17 }                
    18 
    19 int main()
    20 {
    21     test02();
    22     return 0;
    23 }

    运行程序,我们会发现,字符串数组没有被正确输出。下面再看一例:

    3、局部变量地址的返回

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int* func()
     6 {
     7     int a = 10;
     8     return &a;
     9 }
    10 void test01()
    11 {
    12     int* p = func(); //这种调用,结果已经不重要了,因为a的内存(因该是a所指向的内存)
    13                      //被系统释放了,我们没有权限区操作这块内存
    14     printf("test01第一次:a=%d 
    ", *p); //第一次输出‘10’,因为系统默认为作者保留这段内存
    15     printf("test02第二次:a=%d 
    ", *p); //第二次输出内容就不定了,系统已经将这段内存释放了
    16 }
    17 
    18 int main()
    19 {
    20     test01();
    21     return 0;
    22 }

    如果我们用VS2015以上编辑器运行上面代码,控制台会输出注解的内容。如果用codeblock或者其他编辑器运行,则有可能无任何输出,因为你输出的内存数据是无效的。综合起来看,函数不能返回在被调函数中定义的局部变量、数组形式声明的字符串(字符串数组)。因为他们存放在栈上。随着被调函数运行结束,这些局部变量、字符串等占用的内存被释放。再访问上述内存空间就是非法访问了。那么是不是函数就不能返回地址了那?不是!函数可以返回存放在程序数据区、堆区的地址(关于内存分区的内容参见:https://www.cnblogs.com/GoldCrop/p/11030984.html)。详见下面例子:

    4、堆及程序数据区地址的返回

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 char* getString01()
     6 {
     7     char *str= malloc(64);  //在堆上定义字符串
     8     memset(str,0,64);
     9     strcpy(str,"hello,world");
    10     return str;       //返回字符串地址
    11 }
    12 void test02()
    13 {
    14     char *q = getString01();    //接收字符串地址
    15     printf("堆上字符串内容       :%s 
    ", q);  /* 因为字符串地址存放在堆区,即使getString01
    16                                    运行完后,字符串所在内存也不会被释放,可以返回字符串地址 */
    17 }                
    18 
    19 char* getString02()
    20 {
    21     char* str = "hello,world!"; //声明并定义字符串指针变量,字符串存储在数据区
    22     return str;                 //返回指针地址
    23 }
    24 void test03()
    25 {
    26     char* p = NULL;
    27     p= getString02();
    28     printf("程序数据区字符串内容 :%s 
    ", p);
    29 }
    30 int main()
    31 {
    32     test02();
    33     test03();
    34     return 0;
    35 }

     通过上面的例子可以看出,我们能返回程序数据区、堆区变量、常量的地址,但不能返回栈区的变量、常量的地址。

  • 相关阅读:
    Windows统一平台: 开发小技巧
    How to install more voices to Windows Speech?
    Why does my ListView scroll to the top when navigating backwards?
    中文圣经 for Android
    [ CodeVS冲杯之路 ] P1166
    [ CodeVS冲杯之路 ] P1154
    [ CodeVS冲杯之路 ] P1048
    [ CodeVS冲杯之路 ] P1063
    [ CodeVS冲杯之路 ] P3027
    理解矩阵乘法
  • 原文地址:https://www.cnblogs.com/GoldCrop/p/11059318.html
Copyright © 2020-2023  润新知