C语言基础(三)——函数

news2024/11/16 7:42:13

六、函数

6.1 函数的声明与定义—嵌套调用

6.1.1 函数的声明与定义

 函数间的调用关系是,由主函数调用其他函数,其他函数也可以互相调用,同一个函数可以背一个或多个函数调用任意次。

 下例中有两个c文件, func.c是子函数printstar和print_message 的实现,也称定义; main.c是main函数, func.h中存放的是标准头文件的声明和 main函数中调用的两个子函数的声明,如果不在头文件中对使用的函数进行声明,那么在编译时会出现警告。
【例1】函数的嵌套调用

func.c
#include "func.h"

int main() {
    int a=10;
    a=print_star(a);
    print_message();//调用print_message
    print_star(5);
    return 0;
}
func.h

#ifndef FUNCTION_DEFINE_FUNC_H
#define FUNCTION_DEFINE_FUNC_H
#include <stdio.h> //都需要用到这个头文件 就都统一写在这里就行 <>表示从标准库中找头文件
void print_message();   //print_message函数的声明
int print_star(int i); //print_star函数声明。有形参,有返回值
#endif //FUNCTION_DEFINE_FUNC_H
main.c
#include "func.h"  //“”表示在当前路径下找头文件

//print_star的定义
int print_star(int i){
    printf("************************\n");
    printf("print_star %d\n",i);
    return i+3;
}

void print_message(){
    printf("how do you do\n");
    print_star(6); //调用print_star
}

C语言的编译和执行有以下特点:
(1)一个C程序由一个或多个程序模块组成,每个程序模块作为一个源程序文件。对于较大的程序,通常将程序内容分别放在若干源文件中,再由若干源程序文件组成一个C程序。这样处理便于分别编写、分别编译,进而提高调试效率(复试有用).一个源程序文件可以为多个C程序共用。
(2)一个源程序文件由一个或多个函数及其他有关内容(如命令行、数据定义等)组成.一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位而不是以函数为单位进行编译的.main.c和 func.c分别单独编译,在链接成为可执行文件时, main中调用的函数printstar和 print_message才会通过链接去找到函数定义的位置.
(3)C程序的执行是从 main函数开始的,如果在main函数中调用其他函数,那么在调用后会返回到main函数中,在 main函数中结束整个程序的运行.
(4)所有函数都是平行的,即在定义函数时是分别进行的,并且是互相独立的。一个函数并不从属于另一函数,即函数不能嵌套定义,函数间可以互相调用,但不能调用main函数.main函数是由系统调用的,例1.1的 main 函数中调用print_message 函数,而 print_message函数中又调用printstar 函数.我们把这种调用称为嵌套调用. 

6.1.2 函数的分类与调用 

函数分为如下两种
(1)标准函数:即库函数,由系统提供的可以直接使用的,如 printf函数、scanf 函数.不同的C系统提供的库函数的数量和功能会有一些不同,但许多基本的函数是相同的。
(2)用户自己定义的函数:用以解决用户的专门需要.从函数的形式看,函数分为如下两类.
   a.无参函数:一般用来执行指定的一组操作.调用无参函数时,主调函数不向被调用函数传递数据。
   无参函数的定义形式如下:

类型标识符 函数名()
{
    声明部分
    语句部分
}

  例1中, print_message就是无参函数。
  b.有参函数:主调函数在调用被调用函数时,通过参数向被调用函数传递数据。
  有参函数的定义形式如下:

类型标识符函数名(形式参数表列)
{
    声明部分
    语句部分
}

  例1中,printstar就是有参函数,int i对应的i为形参,主调函数和被调用函数之间存在数据传递关系。

6.2 函数的递归调用

6.2.1 递归调用

函数自身调用自身的操作,称为递归函数,递归函数一定要有结束条件,否则会产生死循环!
【例1】n的阶乘的递归调用实现。
分析:f(n)=n*f(n-1); 如5!=5*4!

#include <stdio.h>

int f(int n){
    //一定要有结束条件
    if(1==n){
        return 1;
    }
    return n*f(n-1);    //写公式
}

int main() {
    int n;
    scanf("%d",&n);
    printf("f(%d)=%d\n",n, f(n));
    return 0;
}

【例2】假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?

#include <stdio.h>
//上台阶 ,到第n个台阶 一次只能上一个或两个,有多少种走法
//分析 step(3)=step(2)+step(1)
//    3 = 2 + 1
int step(int n){
    if(1==n||2==n){//当台阶是1个或2个时,递归结束,一个台阶只有一种走法,2个台阶只有两种走法
        return n;
    }
    return  step(n-1)+ step(n-2);
}

int main(){
    int n;
    scanf("%d",&n);
    printf("step(%d)=%d",n, step(n));
    return 0;
}

 递归的核心:找公式,写递归结束条件。

6.3 局部变量与全局变量

6.3.1 全局变量解析-形参-实参解析

在不同的函数之间传递数据时,可以使用的方法如下:
(1)参数:通过形式参数和实际参数。
(2)返回值:用return 语句返回计算结果。
(3)全局变量:外部变量。

#include <stdio.h>

int i=10;//i是一个全局变量,不建议使用 局部变量全局变量重名不会报错 容易搞错
void print(int a)//形参看成一个局部变量
{
    printf("I am print i=%d\n",i);
}

int main() {
    {
        int j=5;
    }//局部变量只在离自己最近的大括号内有效
    int i=5;
    printf("main i=%d\n",i);
    for(int k=0;k<-1;)
    {

    }
//    printf("k=%d\n",k);for循环括号内定义的变量,循环体外不可用
    print(3);
    return 0;
}

全局变量存储,如下图所示,全局变量i存储在数据段,所以main函数和 print函数都是可见的。全局变量不会因为某个函数执行结束而消失,在整个进程的执行过程中始终有效,因此工作中应尽量避免使用全局变量!
在函数内定义的变量都称为局部变量,局部变量存储在自己的函数对应的栈空间内,函数执行结束后,函数内的局部变量所分配的空间将会得到释放。如果局部变量与全局变量重名,那么将采取就近原则,即实际获取和修改的值是局部变量的值.

形参与实参的说明如下:
(1)定义函数中指定的形参,如果没有函数调用,那并不占用内存中的存储单元。只有发生函数调用时,函数print 中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也会被释放。
(2)实参可以是常量、变量或表达式,但要求它们有确定的值,例如, print(i+3)在调用时将实参的值i+3赋给形参。print函数可以有两个形参,如 print( inta,int b)
(3)在被定义的函数中,必须指定形参的类型.如果实参列表中包含多个实参,那么各参数间用逗号隔开。实参与形参的个数应相等,类型应匹配,且实参与形参应按顺序对应,一一传递数据。
(4)实参与形参的类型应相同或赋值应兼容。
(5)实参向形参的数据传递是单向“值传递”,只能由实参传给形参,而不能由形参传回给实参.在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值.
(6)形参相当于局部变量,因此不能再定义局部变量与形参同名,否则会造成编译不通。

6.3.2 外部变量

函数之外定义的变量称为外部变量.外部变量可以为本文件中的其他函数共用,它的有效范围是从定义变量的位置开始到本源文件结束,所以也称全程变量。
关于全局变量需要注意如下几点:
(1)全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。
(2)使用全局变量过多会降低程序的清晰性。在各个函数执行时都可能改变外部变量的值,程序容易出错,因此要有限制地使用全局变量(初试时尽量不用)。
(3)因为函数在执行时依赖于其所在的外部变量,如果将一个函数移到另一个文件中,那么还要将有关的外部变量及其值一起移过去。然而,如果该外部变量与其他文件的变量同名,那么
就会出现问题,即会降低程序的可靠性和通用性.C语言一般要求把程序中的函数做成一个封闭体,除可以通过“实参→形参”的渠道与外界发生联系外,没有其他渠道.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1480920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

光伏气象站的组成

TH-FGF9光伏气象站主要由以下几个部分组成&#xff1a; 光伏组件&#xff1a;光伏组件是光伏气象站的核心部分&#xff0c;其主要功能是将太阳能转化为电能&#xff0c;为气象站的各项设备提供电源。光伏组件通常由多个光伏电池板组成&#xff0c;能够有效地吸收并利用太阳能。…

C++:String类的使用

创作不易&#xff0c;感谢三连&#xff01;&#xff01; 在C语言中&#xff0c;我们想要存储字符串的话必须要用字符数组 char str[]"hello world"这其实是将在常量区的常量字符串拷贝到数组中&#xff0c;我们会在数组的结尾多开一个空间存储\0&#xff0c;这样我…

pyuic生成py文件到指定文件夹

pyuic生成py文件到指定文件夹 关于如何在pycharm配置外部工具的方法这里不做赘述&#xff0c;本文主要说明&#xff0c;如何利用pyuic将ui文件生成到指定的项目目录中。 前提条件&#xff1a;已配置的pyuic工具可以正常使用生成文件到目录中。 一、打开外部工具配置页面 打开…

吸猫毛空气净化器哪个好?推荐除猫毛好的宠物空气净化器品牌

如今&#xff0c;越来越多的家庭选择养宠物&#xff01;虽然家里变得更加温馨&#xff0c;但养宠可能会带来异味和空气中的毛发增多可能会引发健康问题&#xff0c;这也是一个大问题。 但我不想家里到处都是异味&#xff0c;尤其是便便的味道&#xff0c;所以很需要一款能够处…

android Service 与 activity 通信 并不断传数据

注&#xff1a;这只是个Demo 以下载为案例&#xff0c;实现开启下载&#xff0c;暂停下载&#xff0c;下载进度不断发送给activity class DownloadService : Service() {override fun onBind(intent: Intent?): IBinder? {return MyBinder()}inner class MyBinder : Binder…

mysql学习--binlog与gtid主从同步

基础环境 基于centOS7-MySQL8.0.35版本 我们先准备一台主服务器两台从服务器来实现我们主从同步的诉求 Master&#xff1a;192.168.75.142 slave1:192.168.75.143 slave&#xff1a;192.168.75.145 binlog主从同步 主库配置 #我们需要在主从库中都需要添加server_id&am…

如何学习、上手点云算法(一):点云基础

写在前面 本文内容 点云算法的学习基础&#xff0c;入门方法&#xff0c;相关领域&#xff0c;资源&#xff0c;开源库&#xff0c;算法等的介绍&#xff1b; 以Open3D和PCL等为基础工具的点云处理代码讲解、实现&#xff1b; 文中涉及的参考以链接形式给出&#xff0c;涉及文…

综合练习(二)

目录 列出薪金比 SMITH 或 ALLEN 多的所有员工的编号、姓名、部门名称、领导姓名、部门人数&#xff0c;以及所在部门的平均工资、最高和最低工资 补充 spool Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 列出薪金比 SMITH 或 AL…

探索数据结构:解锁计算世界的密码

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty‘s blog 前言 随着应用程序变得越来越复杂和数据越来越丰富&#xff0c;几百万、…

LabVIEW最佳传输系统设计

LabVIEW最佳传输系统设计 介绍了基于LabVIEW软件开发的最佳基带传输系统和最佳带通传输系统的设计。通过软件仿真实现了脉冲成形滤波器和匹配滤波器的设计&#xff0c;证明了系统在消除码间干扰和抗噪声方面的优异性能。此设计不仅激发了学生的学习兴趣&#xff0c;还有助于提…

kubernetes最新版安装单机版v1.21.5

k8s集群由Master节点和Node&#xff08;Worker&#xff09;节点组成。 1.环境 环境&#xff1a;centos 7资源配置&#xff1a;2c4g &#xff08;CPU最少2c&#xff0c;不然k8s起不来&#xff09;docker&#xff1a;25.0.3k8s&#xff1a;1.21.5 2.安装前置环境 [rootbertra…

【Android开发】01-第一个Android APP

一、改MainActivity class MainActivity : AppCompatActivity() {/*因Android的app有生命周期&#xff0c;故入口是OnCreate而不是main函数*/override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main…

Kubernetes的五大开源存储项目

在Kubernetes中&#xff0c;关于数据的持久化管理是一种挑战&#xff0c;对此&#xff0c;社区提供了多种存储的解决方案&#xff0c;这些方案旨在简化和优化容器化应用程序的持久化数据管理。 现介绍 Kubernetes 的五大开源存储项目&#xff0c;带你了解开源存储解决方案的多…

java常用应用程序编程接口(API)——LocalDateTime,LocalDate,LocalTime,ZoneId,ZonedDateTime概述

前言&#xff1a; 在jdk8以后&#xff0c;出现了更多好用的时间相关的api&#xff0c;整理下使用心得。打好基础&#xff0c;daydayup! jdk8以前使用的时间api可以看这篇&#xff1a; java常用应用程序编程接口&#xff08;API&#xff09;——Date&#xff0c;SimpleDateForm…

学校机房Dev c++解决中文乱码问题

工具->编译选项->勾选 编译时加入以下命令 -fexec-charsetGBK -finput-charsetUTF-8 显示中文&#xff1a;工具->编辑器选项->去掉第一个的勾勾。

【多线程】常见锁策略详解(面试常考题型)

目录 &#x1f334; 乐观锁 vs 悲观锁&#x1f38d;重量级锁 vs 轻量级锁&#x1f340;自旋锁&#xff08;Spin Lock&#xff09;&#x1f38b;公平锁 vs ⾮公平锁&#x1f333;可重⼊锁 vs 不可重⼊锁&#x1f384;读写锁⭕相关面试题 常⻅的锁策略 注意: 接下来讲解的锁策略不…

docker报错 fatal error: runtim: out of memory

fatal error: runtim: out of memory 真无语了 系统内存也够用 原来是虚拟机的不够用了 &#xff08;原本1g已经加到2g还是会报错&#xff09; 直接3台虚拟机都加到4g

Maven-install报错:Malformed \uxxxx encoding

把仓库中所有的resolver-status.properties文件全部干掉。 直接ctrla全选中delete全部删除 然后再清idea缓存重启试试

巴塞罗那世界移动大会:华为构建电信公司AI模型——MWC 2024

在巴塞罗那世界移动大会的舞台上&#xff0c;华为宣布推出了一款专为电信公司设计的基础模型——MWC 2024电信基础模型。这一创新技术旨在通过自然语言交互、场景化代理等功能&#xff0c;提升电信行业员工的工作效率&#xff0c;增强用户满意度&#xff0c;进而推动整个行业的…

拦截器Interceptor(黑马学习笔记)

学习完了过滤器Filter之后&#xff0c;接下来我们继续学习拦截器Interceptor。 拦截器我们主要分为三个方面进行讲解&#xff1a; 1.介绍下什么是拦截器&#xff0c;并通过快速入门程序上手拦截器 2.拦截器的使用细节 3.通过拦截器Interceptor完成登录校验功能 我们先学习第一…