首页 > 其他分享 >函数(3)函数原型和参数传递

函数(3)函数原型和参数传递

时间:2023-11-18 23:11:17浏览次数:30  
标签:begin 函数 int sum 参数传递 原型 swap void

<1>函数原型

(1)函数先后关系

我们将自己定义的函数放在主函数main之前—————是因为:C的编译器自上而下顺序分析代码,这样在主函数中调用自定义函数才合理

1.我们以一段代码为例
#include<stdio.h>

void sum(int begin, int end){
int i;
int sum =0;
for ( i=begin; i<=end; i++ ) {
sum += i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}
———————上方为自定义函数,下方为主函数————————————
int main(){
sum(1,10);——————我们以第一次调用为例:

* 在编译器运行到这一步时,它需要知道sum函数形式,所以我们必须在主函数之前对sum函数的形式进行定义(也就是需要了解sum有几个参数,每个参数的类型,以及返回的类型)

sum(20,30);
sum(35,45);
return 0;
}

2.以此类推,我们分析一下自定义函数在主函数下方的情况

1)以一段代码为例:

#include<stdio.h>

int main(){
sum(1,10);——————//编译器会在此处猜测我们的函数类型为int sum(int ,int)
sum(20,30);
sum(35,45);
return 0;
}
void sum(int begin, int end){
int i;
int sum =0;
for ( i=begin; i<=end; i++ ) {
sum += i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}

———我们得出的编译结果显示,sum函数的隐含申明无效(编译器猜测的函数类型与实际定义的函数类型不符),编译失败;

2)原型声明

解决方法:————针对第二种编译失败的代码进行原型声明

我们以一段代码为例:
#include<stdio.h>

void sum(int begin, int end);——————//声明

int main(){
sum(1,10);————//int sum(int,int)我们在之前对函数进行了声明,这里编译器便不会继续猜测函数的类型,而是根据声明来判断对sum的调用是否正确
sum(20,30);
sum(35,45);
return 0;
}
void sum(int begin, int end){——————//定义

//值得注意的是,在此处函数会再次判断定义与声明是否一致//

int i;
int sum =0;
for ( i=begin; i<=end; i++ ) {
sum += i;
}
printf("%d到%d的和是%d\n",begin,end,sum);
}

(2)函数原型

  1. 构成:函数头,以分号结尾;
  2. 目的:告诉编译器定义函数的形式;
  3. 细节:函数原型里面可以省略参数名
    —————即可以将void sum(int begin, int end)表示为void sum(int, int)
    原因:原型声明仅仅是告诉编译器定义函数的参数数量和类型,参数名并不影响,保留参数名是为了增强代码的可读性
  4. 涉及到三个方面
  • 名称
  • 参数(数量及类型)
  • 返回类型

——————区分技巧:有分号的为函数原型,没有分号的为实际函数头

<2>参数传递

(1)调用函数

  • 条件:如果函数有参数,那么调用函数时必须传递给它数量和类型正确的值;
  • 可以传递给函数的值是表达式的结果;
  • 表达式大概分为以下几个类型:
  1. 单个字面量;c=max(4,5)
  2. 单个变量;————c=max(a,b)
  3. 计算的结果;————c=max(23+45,b)
  4. 函数的返回值;————c=max(max(23,45),a)
  5. 赋值;

(2)类型不匹配

  • 调用函数时给的值与参数的类型不匹配是C语言传统上最大的漏洞;
  • 编译器总是悄悄替你把类型转换好,但是这很可能不是你所期望的;
  • 后续的语言,C++/Java在这方面很严格;
1).类型不匹配出现的情况:

我们以一段代码为例:

#include<stdio.h>

void cheer (int i){
printf("cheer %d\n",i);
}
int main(){
cheer(2.4);—————注意:函数原型声明i为整型,而此处cheer中i的值为double型
return 0;
}

类型不匹配的结果:编译器仅可能给出警告,但是仍然能给出结果(编译器会自动进行类型的转换)

(3)调用函数时传递过去的是什么

  • C语言在调用函数时,只能传递值给函数
    我们以一段代码为例:
#include<stdio.h>

void swap(int a,int b);
int main(){
int a=5;
int b = 6;
swap(a,b);
printf("a=%d b=%d\n",a,b);
return 0;
}
void swap(int x,int y){
int t=x;
x=y;
y=t;
}

——1)出现问题:在这串代码的调试过程中我们发现我们得出x,y的值时便不能再输出a,b的值;得出a,b的值,便不能继续输出x,y的值

——2)情况分析:

我们对代码进行一定程度的修改:

#include<stdio.h>

void swap(int a,int b);
int main(){
int a=5;
int b = 6;
swap(a,b);
printf("a=%d b=%d\n",a,b);
return 0;
}
void swap(int a,int b){
int t=a;
a=b;
b=t;
}在进行交换时,我们将swap中a的值5交给swap中int里面的a,将swap中b的值6交给交给swap中int里面的b;swap里面的a,b和main里面的a,b完全没有关系,尽管他们同名,但他们处在不同的位置上,是没有关系的变量

唯一的联系是在调用函数时传递了值

——————所以这串代码不能交换a,b的值。

1.引申定义:传值(对——1)中出现的问题进行解释)

  • 每个函数都有自己的变量空间,参数也位于这个独立空间中,和其它函数没有关系,这也就解释了a,b的值与x,y的值不能同时被输出的问题

2.引申定义:形式参数与实际参数

  • 函数参数表中的参数为形式参数,例如:void swap(int a,int b)中的int a与int b;调用函数时给的值为实际参数,例如:swap(a,b)

注意:为了防止对概念进行混淆,我们可以将形参实参的概念理解为参数和值的关系:

  • 即原来的实参为值,而形参则代表参数,整体可以理解为进行传值的操作

标签:begin,函数,int,sum,参数传递,原型,swap,void
From: https://www.cnblogs.com/QingYuY/p/17841431.html

相关文章

  • vue中遇到的函数执行顺序问题
    vue中遇到的函数执行顺序问题总结:vue中方法和方法间并未严格按照执行顺序执行的,可以使用async和await修饰符,使方法调用和执行是异步的。在vue中的方法调用顺序是依次进行的,方法体内部也是依次执行的,但是,两个方法体的执行顺序并不能严格控制,也就是说,并不一定是先执行完第一个方......
  • python 数据可视化:直方图、核密度估计图、箱线图、累积分布函数图
    本文使用数据来源自2023年数学建模国赛C题,以附件1、附件2数据为基础,通过excel的数据透视表等功能重新汇总了一份新的数据表,从中截取了一部分数据为例用于绘制图表。绘制的图表包括一维直方图、一维核密度估计图、二维直方图、二维核密度估计图、箱线图、累计分布函数图。 目录......
  • 入门c语言--基于c库函数strstr的实现
    #include<stdio.h>#include<assert.h>char*my_strstr(constchar*p1,constchar*p2){ assert(p1&&p2);//检查p1和p2是否为空指针//创建s1,s2来在p1,p2中进行移动,创建指针tmp来保存开始移动时的s1的位置 char*s1=NULL; char*s2=NULL; char*tmp=(char*)p1;//对p1......
  • C字符输入输出函数
    ......
  • Python中四大高阶函数,你认识几个
    1.匿名函数defname(a,b):returna+bf=lambdaa,b:a+bprint(f(15,15))2.map函数第一个参数接收一个函数名,第二个参数接收一个可迭代对象,利用map,lambda表达式将所有偶数元素加100deffun(a,b):returna+bret=map(fun,[1,2,3],[4,5,6])print(list(ret))3.sor......
  • 复变函数
    一、复变函数的基本知识由于在实数域中无法表示负数开根号问题,故将数系进行扩充,定义有\(i^{2}=-1\)1.复数的表示法\[代数形式:z=x+iy\qquad其中i为虚部单位\]\[指数形式:z=re^{i\theta}\qquad其中r为其幅值,\theta为幅角\]\[三角形式:根据欧拉公式,有:z=r(\cos\theta......
  • 前端歌谣-第贰拾贰课-函数参数默认值
    前言我是歌谣最好的种树是十年前其次是现在今天继续给大家带来的是this指向的讲解环境配置npminit-yyarnaddvite-D修改page.json配置端口{"name":"demo1","version":"1.0.0","description":"","main":"index.js",......
  • 函数(2)从函数中返回
    <1>从函数中返回值————————return:如果我们所定义的函数要返回一个结果,那么我们就需要用return将这个结果交给所调用的函数。(1)注意:返回类型我们以一段代码为例:intisprime(inti){intret=1;intk;for(k=2;k<i-1;k++){if(i%k==0){ret=0;break;}}returnret;......
  • mysql函数常见字符串函数
    1、BIT_LENGTH返回值为二进制的字符串str长度。--格式:BIT_LENGTH(str)selectBIT_LENGTH('abc'); 2、CONCAT返回结果为连接参数产生的字符串。--格式:concat(str1,str2,…)selectCONCAT('a','b','c')   3、ELT假设n等于1,用这个n去跟后一个数比较,如果n大......
  • mysql函数常见数学函数
    1、ABS(x)返回x的绝对值 --格式:ABS(X)selectABS(23) 2、PI()返回圆周率π,默认显示6位小数--格式:PI()selectPI()  3、SQRT(x)返回非负数的x的二次方根--selectSQRT(X)selectSQRT(2)    4、MOD(x,y)返回x被y除后的余数--selectMOD(......