• 函数的形参和实参的关系(摘自《CPrimer 中文版第六版》第9章及黑马程序员 2018C语言提高深入浅出ch1-6)


    首先,摘抄一段《CPrimer》的内容:

    1、形式参数是被调函数中的变量,实际参数是主调函数赋给被调函数的具体值。实际参数可以是常量、变量,或甚至是更复杂的表达式。无论实际参数是何种形式都要求被求值,然后该值被拷贝给被调函数相应的形式参数。再次强调:实际参数是具体的值(哪怕是以变量、表达式等形式存在,在传递给被调函数时,也要先转换成具体的值),该值要被赋给作为形式参数的变量。

    2、因为被调函数使用的值是从主调函数中拷贝而来,所以无论被调函数对拷贝数据进行什么操作,都不会影响主调函数中的原始数据。

    总结一下:

    1、实际参数在传递给被调函数的时候是具体值,我们不必关心它原来的形式(哪怕是变量、表达式等等)。形式参数是变量,在被调用执行的过程中,形参变量是要被创建并占用栈上的空间的,而这个形参变量的值,从实参拷贝而来。

    2、由于形参变量被创建并占用栈上空间,所以在被调用函数运行时,形参所发生的任何变化,都不会影响实参,因为它们是彼此独立的两个变量(这里暂且把实参当成变量)。下面看例程:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define  NAME "高德科技"
    #define ADDRESS "阳光街1号"
    #define PLACE "207室"
    #define WIDTH 40
    #define SPACE ' '
    
    void show_n_char(char ch,int num);
    int main()
    {
        int spaces;
        show_n_char('*',WIDTH);  //打印40个*
        putchar('
    ');  //putchar("
    ") 不行
        show_n_char(SPACE,12); //打印12个空格
        printf("%s 
    ",NAME);  //打印单位名称
        spaces=(WIDTH-strlen(ADDRESS));  //计算40-ADDRESS后,剩余长度。spaces作为show_n_char函数的实参,算出确切的值
        show_n_char(SPACE,spaces);  //打印spaces个长度的空格,以便让ADDRESS靠右
        printf("%s 
    ",ADDRESS); //打印地址
        show_n_char(SPACE,(WIDTH-strlen(PLACE))/2); //打印1/2个WIDTH-PLACE长度的空格
        printf("%s 
    ",PLACE);                      //以便让PLACE居中
        show_n_char('*',WIDTH);     //打印40个*
        putchar('
    ');              //换行
    
        return 0;
    }
    void show_n_char(char ch,int num)
    {
        for(int count=1;count<=num;count++) putchar(ch);
    }

     下面这个例程能更好地说明上面的2条总结:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void allocateString(char* pp) //声明了字符指针形参——pp,当这个函数被调用时,编译器在栈上会真实地创建这个变量pp
    {   
        printf("pp的地址是: %p, pp=%s 
    ", &pp, pp);
        char* temp = malloc(100);   //创建临时字符指针
        if (temp == NULL) return;
        memset(temp, 0, 100);
        strcpy(temp, "Hello,world!");  //上面3条语句是初始化及赋值
        printf("temp的地址是: %p, temp=%s 
    ", &temp, temp);
        pp = temp;              //将临时变量temp的地址赋给pp。注意:仅仅改变了pp的值!并没有对调用函数提供的实参p作任何改动
        printf("pp的地址是: %p, pp=%s 
    ", &pp, pp);
    }
    void test02(void)
    {
        char* p = NULL;  //创建字符指针pp,并初始化。
        printf("p的地址是: %p, p=%s 
    ", &p, p);
        allocateString(p);  //调用allocateString函数,并将‘NULL’这个值拷贝给它的形参——pp
        printf("实参p=%s  
    ", p);
        printf("p的地址是:%p 
    ", &p);
    }
    
    int main()
    {
        test02();  //调用函数,得到输出:“传递同级指针得:(null)”
        system("pause");
        return EXIT_SUCCESS;
    }

    从上面程序能看出:p,pp,temp三个变量在内存中的位置相近,显然,编译器在栈上都给分配了内存。

    画个图,仔细分析程序对内存的操作:

  • 相关阅读:
    批量修改数据后应收集统计信息
    this,this,再次讨论javascript中的this,超全面
    javascript中的闭包,超简单论述,保证小学生必懂
    有四中方法可以实现PHP的伪静态,你造吗?
    javascript 事件传播与事件冒泡,W3C事件模型
    浅谈asp.net性能
    div浮动层 兼容IE FF
    我们这些程序员
    c++学习笔记_1
    windows下hexo+github搭建个人博客
  • 原文地址:https://www.cnblogs.com/GoldCrop/p/10921726.html
Copyright © 2020-2023  润新知