C语言学习——函数

server/2024/11/13 15:30:59/

目录

八、函数

8.1概述

8.2函数定义的一般形式

无参函数

有参函数

空函数

8.3函数参数和函数的值

形式参数和实际参数

函数的返回值

8.4函数的调用

函数调用的一般形式

函数调用的方式

1.函数语句

2.函数表达式

3.函数参数

对被调用函数的声明和函数原型

8.5函数的嵌套调用

8.6函数的递归调用


八、函数

8.1概述

        一个较大的程序一般应分为若干程序模块,每一个模块用来实现一个特定的功能。所有高级语言中都有子程序这个概念,用子程序实现模块的功能。在C语言中,子程序的作用是由函数来完成的。一个C程序可由一个主函数和若干函数来构成的。由主函数调用其他函数,其他函数也可以相互调用。同一个函数可以被一个或者多个函数调用任意多次。

        在程序开发中,常将一些常用的功能模块编写成函数,放在公共函数库供大家选用。所以,我们要善于利用函数,以减少重复编写程序段的工作量。

8.2函数定义的一般形式

无参函数

定义无参函数的一般形式:

类型标识符 函数名 ()

{

声明部分

语句部分

}

有参函数

定义有参函数的一般形式:

类型标识符 函数名 (形式参数表列)

{

声明部分

语句部分

}

例如:

int max(int x, int y)
{int z;      //函数体中的声明部分z = x>y?x:y;return z;
}

如果在定义函数时不指定函数类型,系统会隐含指定函数类型为int型。因此上面定义的max函数左端的int可以省写。

空函数

空函数的定义形式为:

类型说明符 函数名()

{ }

例如:

int dummy(){}

8.3函数参数和函数的值

形式参数和实际参数

在调用函数时,大多数情况下,主函数和调用函数之间有数据传递的关系。这就是前面提到的有参函数。

在定义函数时函数名后面括号中的变量名称为“形式参数”,简称“形参”。

在主函数中调用一个函数时,函数后面括号中的参数(可以是一个表达式)称为“实际参数”,简称“实参”

调用函数时的数据传递

#include<stdio.h>
​
int main()
{int max(int x, int y);   //对max函数声明int a,b,c;scanf("%d%d",&a,&b);c = max(a,b);printf("max is %d\n",c); return 0;} int max(int x, int y)
{int z;z = x>y?x:y;return z;
}

关于形参和实参的说明:

  • 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数max中的形参才被分配到内存单元,在调用结束后,形参所占的内存单元也被释放。

  • 实参可以是常量、变量或表达式。例如:max(3,a+b),但是要求他们有确定的值,在调用时将实参的值赋给形参。

  • 在被定义的函数中,必须指定形参的类型。

  • 实参和形参的类型应相同或赋值兼容。

  • 在C语言中,实参向形参的数据传递是“值传递”,单向传递,只由实参传给形参,而不能有形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。

    在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。

函数的返回值

通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数的返回值。下面对函数值作一些说明:

(1)函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定的值带回主调函数中去。如果需要从被调用函数带回一个函数值(供主函数使用),被调用函数中必须包含一个return语句。如果不需要从被调函数带回函数值可以不要return语句。

return语句后面的括号也可以不要,如“return z”等价于“return (z)”。

return后面的值可以是一个表达式。

(2)函数值的类型函数的返回值属于某一确定的类型,所以,应当在定义函数时指定函数值的类型。

在C语言中,凡不加类型说明的函数,自动按整型处理。

(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。

如果函数值的类型和return语句中表达式的类型不一致,则以函数类型的为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。

返回值类型于函数类型不同。将上面的代码稍作改动(注意:是变量的类型改动)

#include<stdio.h>
​
int main()
{int max(float x, float y);   //对max函数声明float a,b;int c;scanf("%f%f",&a,&b);c = max(a,b);printf("max is %d\n",c); return 0;} int max(float x, float y)
{float z;  z = x>y?x:y;return z;
}
//输入 1.5 2.5
//输出:max is 2

解释:函数max定义为整型,而return语句中的z为实型,二者不一致。按上述规定,现将z转换为整型,然后max(x,y)带回一个数值2返回主调函数main。如果将main函数中的c定义为实型,用%f格式输出,也是输出2.000000。

(4)对于不带回值的函数,应当用“void”定义函数为“无类型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调函数的返回值。此时,在函数体中不得出现有返回值的return语句。

8.4函数的调用

函数调用的一般形式

函数名(实参表列)

  • 如果是调用无参函数,则:实参表列“可以没有,但括号不能省略。

  • 如果实参表列包含多个实参,则各个参数间用逗号隔开。

  • 实参和形参的个数应相等,类型应匹配。

  • 实参和形参按顺序对应,一一传递数据。

函数调用的方式

按函数在程序中出现的位置来分,可以有以下3种函数调用方式。

1.函数语句

把函数调用作为一个语句。这时不要求函数带回值,只要求函数完成一定的操作。

max();
2.函数表达式

函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值一参加表达式的计算。

c = 2*max(a,b); //max只是表达式的一部分
3.函数参数

函数调用作为一个函数的实参。例如:

//1.
m = max(a,mx(b,c));
//2.
printf("%d",max(a,b));

函数调用作为函数的参数,实质上也是函数表达式形式调用的一种,因为函数参数本来就要求表达式形式。

对被调用函数的声明和函数原型

在一个函数中调用另一个函数(即被调用函数)需要具备的条件如下。

  • 首先调用的函数必须是已经存在的函数(是函数库或者用户自己定义的函数)。

  • 如果使用库函数,还应该在本文件开头用#include命令将调用有关函数时所需用到的信息“包含”到本文件中。

  • 如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在同一文件中),应该在主调函数中队被调用的函数作声明。

函数原型的一般形式有两种:

  • 函数类型 函数名(参数类型1,参数类型2,··· 参数类型n);

  • 函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2, ··· ,参数类型n 参数名n);

8.5函数的嵌套调用

C语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能包含另一个函数。

C语言不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。

8.6函数的递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。C语言的特点之一就是在于允许函数的递归调用。例如:

int f(int x)
{int y,z;z=f(y);return (2*z);
}

递归调用会无终止的自身调用。而程序中是不应该出现这种情况的,而应出现有限次数、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用;否则就不再继续。

声明:本文章为个人学习笔记,资料整理参考谭浩强《C程序设计(第三版)》如有错误,欢迎大家指正!


http://www.ppmy.cn/server/100132.html

相关文章

记录一次.gitignore 失效问题

前言 今天使用git同步同事的代码时&#xff0c;出现一个问题&#xff0c;.gitignore限制失效&#xff0c;导致我本地生成的临时缓存文件被跟踪到了commit中&#xff0c;执行 git rm --cache .后再add commit也不行&#xff0c;很奇怪就研究了一下&#xff0c;下面将我的解决方…

基于Spring Boot的社区团购系统

目录 前言 功能设计 系统实现 获取源码 博主主页&#xff1a;百成Java 往期系列&#xff1a;Spring Boot、SSM、JavaWeb、python、小程序 前言 随着社会进步和科技发展&#xff0c;信息化时代为各行各业带来了巨大的变革。计算机技术的先进性和普及性使得信息系统的开发变…

前端(HTML + CSS)小兔鲜儿项目(仿)

前言 这是一个简单的商城网站&#xff0c;代码部分为HTML CSS 和少量JS代码 项目总览 一、头部区域 头部的 购物车 和 手机 用的是 文字图标&#xff0c;所以效果可以和文字一样 购物车右上角用的是绝对定位 logo用的是 h1 标签&#xff0c;用来提高网站搜索排名 二、banne…

模型意识对比学习:摆脱训练中的一致性-容忍度困境

论文出处: ICML2023 Model-Aware Contrastive Learning: Towards Escaping Uniformity-Tolerance Dilemma in Training 什么是uniformity-tolerance困境? 温度参数 τ 的设置会影响模型性能 如果 τ 太小,模型会对训练不足的阶段施加过大的惩罚,导致难以区分潜在阳性样本,…

网络协议 十一 ARP,RARP,icmp,websocket,webservice,HTTPDNS,FTP,邮件相关的协议, SMTP,POP,IMAP

ARP 已知IP 求 MAC 的过程 RARP 已知MAC 求 IP 的过程&#xff0c;已被DHCP取代 ICMP websocket 协议&#xff0c;html5中提出的前端使用协议 webservice 技术&#xff0c;已过时 HTTPDNS 之前我们要获得 某一个域名的 IP &#xff0c;要通过DNS协议 去 运营商的ISP 查询&…

金融同业业务

信用拆借&#xff08;Interbank Lending&#xff09; 信用拆借&#xff08;Interbank Lending&#xff09;是指银行之间相互借贷资金的行为&#xff0c;是金融市场中重要的一部分。 定义和机制 1.定义&#xff1a;信用拆借是指银行或者其他金融机构之间在短期内相互借贷资金&a…

修改ubuntu的终端显示语言为英文,界面保持为中文

修改ubuntu的终端显示语言为英文&#xff0c;界面保持为中文 sudo nano /etc/default/locale LANGzh_CN.UTF-8nano ~/.bashrc 在文件未尾加入下列两行 export LANGen_US.UTF-8 export LANGUAGEen在终端执行 source ~/.bashrc之后提示语言就变成英文了

LVS详解

一、概念简述 1.1LVS概念简述 1.1.1 LVS LVS&#xff08;Linux Virtual Server&#xff09;即Linux虚拟服务器&#xff0c;是由章文嵩博士主导的开源负载均衡项目&#xff0c;目前LVS已经被集成到Linux内核模块中。LVS基于内核网络层工作&#xff0c;有着超强的并发处理能力&…