函数的形参和实参的关系(摘自《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('\n');  //putchar("\n") 不行
    show_n_char(SPACE,12); //打印12个空格
    printf("%s \n",NAME);  //打印单位名称
    spaces=(WIDTH-strlen(ADDRESS));  //计算40-ADDRESS后,剩余长度。spaces作为show_n_char函数的实参,算出确切的值
    show_n_char(SPACE,spaces);  //打印spaces个长度的空格,以便让ADDRESS靠右
    printf("%s \n",ADDRESS); //打印地址
    show_n_char(SPACE,(WIDTH-strlen(PLACE))/2); //打印1/2个WIDTH-PLACE长度的空格
    printf("%s \n",PLACE);                      //以便让PLACE居中
    show_n_char('*',WIDTH);     //打印40个*
    putchar('\n');              //换行

    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 \n", &pp, pp);
    char* temp = malloc(100);   //创建临时字符指针
    if (temp == NULL) return;
    memset(temp, 0, 100);
    strcpy(temp, "Hello,world!");  //上面3条语句是初始化及赋值
    printf("temp的地址是: %p, temp=%s \n", &temp, temp);
    pp = temp;              //将临时变量temp的地址赋给pp。注意:仅仅改变了pp的值!并没有对调用函数提供的实参p作任何改动
    printf("pp的地址是: %p, pp=%s \n", &pp, pp);
}
void test02(void)
{
    char* p = NULL;  //创建字符指针pp,并初始化。
    printf("p的地址是: %p, p=%s \n", &p, p);
    allocateString(p);  //调用allocateString函数,并将‘NULL’这个值拷贝给它的形参——pp
    printf("实参p=%s  \n", p);
    printf("p的地址是:%p \n", &p);
}

int main()
{
    test02();  //调用函数,得到输出:“传递同级指针得:(null)”
    system("pause");
    return EXIT_SUCCESS;
}

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

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

 

posted @ 2019-05-25 11:00  大老菜  阅读(441)  评论(0编辑  收藏  举报