一、  函数的值传递

函数的值传递是指参数为基本类型时,如整型、浮点型、字符型(特指单字符型)时,参数传递时是从实参拷贝一份值传给形参,形参的变化不会影响实参的值。

  1. 1.        基本类型做参数

基本类型:是指整型(short int long等)、浮点型(float、double)、字符型(char特指单字符型)

当参数为基本类型时,属于值传递,注意以下几点:

(1)函数的实参和形参分别占有存储单元

(2)函数的实参复制一份值传给形参

(3)实参不会随着形参的变化而变化

例如:

int fun(int x, int y)

{

x++;

y++;

       return x+y;

}

void main()

{

       int a,b;

    int result;

scanf(“%d%d”,&a,&b);

result=fun(a,b);  //此处为函数调用 实参a,b

printf(“result=%d\n”,result);

printf(“a=%d,b=%d\n”,a,b);

}

根据此例子我们可以分析实参是a,b;而形参是x,y。由于x、y的类型是基本类型,可知该函数fun是值传递函数。根据注意事项可知a,b与x,y是分别占有存储单元的。传递的时候是a,b的值复制一份传给x,y的;那么x++;y++;形参发生改变,不会影响实参a,b的值。假设从键盘输入的a,b的值分别是3,4,根据图示来理解整个过程。

(1)实参与形参分别占有存储单元,传递的时候是将值的拷贝传给形参

(2)当函数中语句x++; y++;执行后,形参x、y的值发生改变,而并不会影响实参a、b的值

如上例子运行输入3,4后,计算结果是9,但是a和b的值没有发生变化,还是3和4,这就是值传递的特点。

二、  函数的地址传递

函数的地址传递是指参数是:数组或指针类型时,传递的是地址,而不是值。注意地址传递有以下特点:

(1)函数的实参和形参共享存储单元

(2)函数是将实参的地址传给形参

(3)实参会随着形参的变化而变化,参数类型为:数组和指针

  1. 1.        数组做参数

例如,有一个数组保存着所有5名学生的考试成绩,利用数组做参数求这5名学生的平均值。

float getAverage(int a[],int len)  //数组做参数时,需要两个参数数组名和数组长度

{

       int i,sum=;

    for(i=;i<len;i++)

       {

          sum+=a[i];

       }

    return (float)sum/len;

}

void main()

{

       int a[]={,,,,};

    printf(“平均成绩是%.2f\n”,getAverage(a,)); //数组做参数调用时只写数组名不写[]

}

数组做参数特点:

(1)数组做参数传递的是数组的首地址。

(2)数组名表示数组的首地址(因此调用时候只写数组名)

(3)数组做参数属于地址传递,传递的是数组的首地址,或数组第一个元素的地址。

  1. 2.        指针做参数

例子:使用指针交换两个整数

void swap(int *p,int *q)  //指针做函数的参数

{

       int t;

    t=*p;

*p=*q;

*q=t;

}

void main()

{

       int a,b;

    scanf(“%d%d”,&a,&b);

    swap(&a,&b);  //函数调用传递的地址,所以需要加&

    printf(“a=%d\tb=%d\n”,a,b);

}

我们可以发现两个数确实实现了交换,说明实参会随着形参的变化而变化,揪其根本原因是因为实参和形参是共享存储单元的,调用过程只是将地址(即门牌号)传给形参。

起初变量a,b的值是3、4;将地址传给p、q两指针,则p、q指向a、b两变量如图所示:

执行t=*p; *p=*q; *q=t;三句后,内存中发生了变化:

三、  结构体数组做参数

综上所述,数组可以做为函数的参数,数组做参数属于地址传递,数组可以是基本类型的数组:整型数组、浮点型数组、字符数组,当然数组也可以复杂类型的数组--结构体数组。当参数为结构体数组时,仍是值传递。

例子:创建手机结构体:包括编号、名称、价格、产地。输入五款手机,计算5款手机的平均价格。


struct phone

{

       int id;           //编号

       char name[];   //名称

       float price;       //单价

       char loc[];     //产地

};

float fun(struct phone p[],int len)//计算手机的平均值

{

       int i;

       float avg,sum=;

       for(i=;i<len;i++)

       {

              sum+=p[i].price;  //p是结构体数组名 进行累加

       }

       return sum/len;

}

void main()

{

       struct phone p[];

       int i;

       for(i=;i<;i++)

       {

              printf("请输入第%d款手机的信息:\n",i+);

              printf("\t\t请输入手机编号:");

              scanf("%d",&p[i].id);

              printf("\t\t请输入手机名称:");

              scanf("%s",p[i].name);

              printf("\t\t请输入手机单价:");

              scanf("%f",&p[i].price);

              printf("\t\t请输入手机产地:");

              scanf("%s",p[i].loc);

       }

       printf("五款手机的平均价格是%.2f元\n",fun(p,));//结构体数组做参数只写数组名,并告知数组长度

}

运行结果如图所示:

可见数组做参数传递的是数组首地址,调用时只写数组的名字,不需要中括号等,同时需要知道数组的长度。结构体数组做参数和普通数组做参数本质是一样的,只是要针对性处理结构体数组的每一个元素而已。

四、  结构体指针做参数

根据指针做参数的特点,可知指针做参数是地址传递的一种。结构体指针只不过是一种指向结构体这种复杂自定义类型的指针而已,并没有什么不同。

例如:根据上一例子的手机结构体,实现结构体指针做参数,传递过去计算打折,手机单价6000以上打8折,300以上打9折,3000以下原价但送优惠券。

struct phone

{

       int id;          

       char name[];  

       float price;     

       char loc[];   

};

void fun(struct phone *p)

{

       if(p->price>)

       {

              printf("手机价格超过6000,享受8折优惠,最终消费金额是%.2f元\n",p->price*0.8);

       }

       else if(p->price>)

       {

              printf("手机价格超过3000,享受9折优惠,最终消费金额是%.2f元\n",p->price*0.9);

       }

       else

       {

              printf("手机价格不足3000,暂无优惠,送您优惠券一张,最终消费金额是%.2f元\n",p->price);

       }

}

void main()

{

       struct phone p;

       printf("\t\t请输入手机编号:");

       scanf("%d",&p.id);

       printf("\t\t请输入手机名称:");

       scanf("%s",p.name);

       printf("\t\t请输入手机单价:");

       scanf("%f",&p.price);

       printf("\t\t请输入手机产地:");

       scanf("%s",p.loc);

       fun(&p);  //调用时传递的地址,因为参数是指针类型

}

这种参数传递属于地址传递,传递的是变量的地址。可以简单的理解为告诉了这个变量家的门牌号,这样去修改的时候,变量就真的会发生变化。效果图如下:

学生信息管理系统

/* Note:Your choice is C IDE */
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int i,p;
int a[],s;//s为总和
int b;
int mima(){
char mima[],name[];
printf("请输入账户:\n");
scanf("%s",&name);
printf("请输入密码:\n");
scanf("%s",&mima);
for (i=;i<;i++){
if(strcmp(mima,"")==&&strcmp(name,"杨建")==){
return ;
}else{
printf("输入错误,您还有%d次机会",-i);
}
i++;
}
return ;
}
void show_meun(){
printf("\n\n\t\t\t══成绩管理系统══\n");
printf("\t\t\t 1.输入成绩\n");
printf("\t\t\t 2.输出成绩\n");
printf("\t\t\t 3.总成绩\n");
printf("\t\t\t 4.平均成绩\n");
printf("\t\t\t 5.最高成绩\n");
printf("\t\t\t 6.最低成绩\n");
printf("\t\t\t 7.排序\n");
printf("\t\t\t 8.成材率\n");
printf("\t\t\t 0.退出\n");
printf("\t\t\t 9.刷新\n");
}
void input(){
for(i=;i<;i++){
printf("请输入第%d个人的成绩:",i+);
scanf("%d",&a[i]);
}
}
void output(){
for(i=;i<;i++){
s=s+a[i];
printf("第%d个人分数为%d\n",i+,a[i]);
} }
void All_score(){
printf("总成绩为%d",s);
} void Max_score(){
for(i=;i<;i++){
if(b<a[i]){
b=a[i];
}
}
printf("最大值为%d",b);
}
void Min_score(){
for(i=;i<;i++){
if(b<a[i]){
b=a[i];
}
}
printf("最大值为%d",b);
}
void Average_score(){
b=s/;
printf("平均分数是%d",b);
}
void manage_number(){
for(i=;i<;i++){
if(a[i+]>a[i]){
b=a[i+];
a[i+]=a[i];
a[i]=b;
}
}
for(i=;i<;i++){
s=s+a[i];
printf("第%d名分数为%d",i+,a[i]);
} }
void Good(){
int x;
for(i=;i<;i++){
if(a[i]>=){
x++;
}
}
printf("成材率为%.2f%%\n",x*);
}
void main()
{
if (mima()==){
show_meun();
}
for(i=;i>;i++){
printf("请输入功能编号:");
scanf("%d",&p);
switch (p){
case :input();break;
case : output();break;
case : All_score();break;
case : Average_score();break;
case : Max_score();break;
case : Min_score();break;
case : manage_number();break;
case : Good();break;
case : exit();break;
case : system("cls");break;
default :printf("---------------------\n");
}//switch
}//for
}//zuihou

c语言进阶9-值传递与地址传递的更多相关文章

  1. C语言 值传递和地址传递

    不少同学在学到C语言的指针部分时感到很困惑,对经常提到的"值传递"和"地址传递"两个概念弄不 明白.实际上,因为地址本身也可以作为一个特殊的"值&qu ...

  2. C语言:值传递,地址传递和引用传递(example:值交换)

    于C语言中值传递.地址传递和引用传递的我个人理解. 通过一个例子:swap(交换两个整型变量的值)来表现! #include <stdio.h> void swap1(int* a,int ...

  3. C语言参数传递(值传递、地址传递)+二级指针

    参数传递 C语言参数传递一般分为:值传递和地址传递(本质上只有值传递) (注意:C语言中没有引用传递,C++才有引用传递,因为很多C语言环境是用C++编译器编译,使得C看起来支持引用传递,导致很多网上 ...

  4. “equals”有值 与 “==”存在 “equals”只是比较值是否相同,值传递,==地址传递,null==a,避免引发空指针异常,STRING是一个对象==null,对象不存在,str.equals("")对象存在但是包含字符‘''

    原文链接:http://www.cnblogs.com/lezhou2014/p/3955536.html "equals" 与 "==" "equa ...

  5. go语言基础之结构体做函数参数 值传递和地址传递

    1.结构体做函数参数值传递 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

  6. c#基础语言编程-按值类型和引用类型传递参数

    引言 在介绍传递参数介绍前,请明白参数类型和传递方式是不同的.传递方式分为按值类型和引用类型传递参数.参数类型有值类型和引用类型,这个和C++是不同的.这里的传递方式对应c++中的深复制和浅复制. 两 ...

  7. Java中的值传递和地址传递(传值、传引用)

    首先,不要纠结于 Pass By Value 和 Pass By Reference 的字面上的意义,否则很容易陷入所谓的“一切传引用其实本质上是传值”这种并不能解决问题无意义论战中.更何况,要想知道 ...

  8. Java中不得不谈的值传递和地址传递

    个人的一些认识,希望能对初学Java的你,或者困惑于方法参数传递的你祈祷一丝帮助! 下面是一些作者的个人观点,如果有错,欢迎各位大牛指出错误,灰常感谢您的观看与支持... -------------- ...

  9. C#函数的参数传递方式1(值传递与地址传递)

    using System; namespace class1 { class program { static void Main(string[] args) { //值传递引用,实际参数不会变化 ...

随机推荐

  1. springmvc登录拦截jsp页面

    web.xml配置 <filter> <filter-name>LoginFilter</filter-name> //编写拦截的类的全类名 <filter- ...

  2. JavaScript规定了几种语言类型?

    JavaScript中的每一个值都有它自己的类型,JavaScript规定了七种语言类型: 1.Undefined 2.Null 3.Boolean 4.String 5.Number 6.Symbo ...

  3. python集合的内建函数

    s.issubset(t) 如果s 是t 的子集,则返回True,否则返回False s.issuperset(t) 如果t 是s 的超集,则返回True,否则返回False s.union(t) 返 ...

  4. C#中await/async闲说

    自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要从底层开始编写,这样后边使用的时候 ...

  5. 关于linux网卡消失的问题

    首先我也是一名学生,在学习的过程Linux的过程中,因为老师要求配置hadoop集群所以就匆匆忙忙的上手了,但是在配置网络的问题时遇到了网卡消失的问题 我在网上询问了许多的人,但是还是没有找到一个很好 ...

  6. C++几个细节(1)

    标签: C++ 1. 类的初始化 几种不同初始化的区别: A a;和A *a=new A()的区别,示例程序如下: #include <stdio.h> #include <stri ...

  7. sails连接monogodb数据库

    1.全局安装:cnpm install -g sails 2.命令窗口进入项目位置 新建项目:sails new sails_cqwu --fast,选择2(快速建立sails项目) 3.cd进入sa ...

  8. Kafka 学习之路(二)—— 基于ZooKeeper搭建Kafka高可用集群

    一.Zookeeper集群搭建 为保证集群高可用,Zookeeper集群的节点数最好是奇数,最少有三个节点,所以这里搭建一个三个节点的集群. 1.1 下载 & 解压 下载对应版本Zookeep ...

  9. 【win10家庭版】删除文件提示没有权限最简单的方式(已验证)

    趁着618入了新本本,预装了家庭普通版Win10,但是实际使用中遇到了一些问题.问题不大,但是着实反人类,在此吐槽! 问题: 首先,进入系统会提示你建一个账号,建立完成登录系统.本账户拥有Admini ...

  10. Linux 勿卸载软件,所有命令不能用了咋办

    1. 一次有趣的事 有个做技术的(不说什么岗位,容易被人喷,谁都有失手的时候),在公司的业务测试环境的机器,卸载了一个软件rpm -e --nodeps filesystem* , 导致机器所有的命令 ...