【C语言必经之路——第6节】函数内容总结

2023-10-19 23:59

本文主要是介绍【C语言必经之路——第6节】函数内容总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、什么是函数

二、C语言中的函数

1、分类

2、库函数

3、自定义函数

(1)函数的定义

 (2)函数的参数

(3)函数的调用

(4)作用域

(5)声明与定义

三、多维数组作参数

四、函数的嵌套调用和链式访问

1、嵌套调用

2、链式访问

 五、函数的递归与迭代

1、函数递归

2、函数迭代

3、举例


一、什么是函数

程序是由多个零件组合而成的,而函数就是这种“零件”的一个较小的单位。也可以叫子程序。

在计算机科学中,子程序是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。

二、C语言中的函数

1、分类

1. 库函数
2. 自定义函数

2、库函数

在开发过程中常用的基础功能,它们不是业务性的代码,这些在开发的过程中每个程序员都可能用的到,为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。使用库函数,必须包含 #include 对应的头文件。

C语言常用的库函数都有:

  • IO函数
  • 字符串操作函数
  • 字符操作函数
  • 内存操作函数
  • 时间/日期函数
  • 数学函数
  • 其他库函数

如何学习库函数,在这里笔者推荐几个网站:

www.cplusplus.com
http://en.cppreference.com(英文版)
http://zh.cppreference.com(中文版)

3、自定义函数

自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计,针对不同的功能用不同的函数来实现。

(1)函数的定义

ret_type fun_name(para1, * )
{
        statement;  //语句项
}

ret_type 返回类型
fun_name 函数名
para1   函数参数

这里我们从一个例子细分析函数的组成

int  max2 ( int a, int b )              ·接收int型的形参a、b。{  if ( a > b)                        ·求较大值。return a;                        else                                  return b;}                                     ·将求得的int型的值返回到调用源。

函数头( function header )
        该部分表示函数的名称和格式。包含返回类型、函数名、形参声明三部分

返回类型( return type )
        函数返回的值——返回值(return value)的类型。上述函数的情况下,返回的是两个int型数值中较大的一个,所以其类型是int。

函数名( function name )
        函数的名称。从其他零件调用函数时,使用函数名。

形参声明( parameter type list )                                                                                                                 小括号括起来的部分,是用于接收辅助性提示的变量——形式参数的声明。像该函数这样接收多个形参的情况下,使用逗号将它们分隔开来。

                       函数max2中,a和b都被声明为了int型的形参。

 函数体( function body )
        函数体是复合语句。仅在某个函数中使用的变量,原则上应在该函数中声明和使用。但要注意不能声明和形参同名的变量,否则会发生变量名冲突的错误。

 (2)函数的参数

实际参数(实参)
        真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
参。
形式参数(形参)
        形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才分配内存单元,所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有
效。形式参数分配内存单元之后其实相当于实参的一份临时拷贝。

 

可以发现形参x,y与实参num1和num2的地址不同,而且第一次调用时主函数内的实参并没有交换,当第二次实参传地址,用形参指针接收时,数值才交换成功。可以看出来形参和实参并不是一个东西,只是将对应的值传给了形参在函数内部进行使用。还可以发现函数内部的“活动”不影响外函数的运行,只有进行传址调用,外函数的值才会与调用函数内部同步变化。

(3)函数的调用

传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。
笔者的理解
形参是传来了地址,而且函数内容是对其所指的变量进行相关操作,这样就是传址调用,是可以对外部函数进行改变的。形参接收了地址而且函数是对地址操作,或者形参接收变量,函数对变量进行操作,这样就是传值调用,这样的函数对外部函数是不起作用的,操作区域只在函数内部。
三个例子

<1>传入地址,操作地址——不会影响实参

#include <stdio.h> 
void fun(int *a,int *b)
{int *c;c=a;a=b;b=c;
}
int main()
{int x=3, y=5,*p=&x, *q=&y;fun(p, q);printf("%d %d\n", *p, *q);fun(&x, &y);printf("%d %d\n", *p, *q);
}

 <2>传入变量值,操作变量——不会影响实参

#include <stdio.h>
void Swap1(int x, int y)
{int tmp = 0;tmp = x;x = y;y = tmp;
}int main()
{int num1 = 1;int num2 = 2;Swap1(num1, num2);printf("Swap1::num1 = %d num2 = %d\n", num1, num2);return 0;
}

 <3>传入地址,操作变量——能够影响实参

#include<stdio.h>void Swap2(int* px, int* py)
{int tmp = 0;tmp = *px;*px = *py;*py = tmp;
}int main()
{int num1 = 1;int num2 = 2;Swap2(&num1, &num2);printf("Swap2::num1 = %d num2 = %d\n", num1, num2);return 0;
}

(4)作用域

        赋给变量的标识符,它的名称都有一个通用的范围,称为作用域
        在程序块(复合语句)中声明的变量的名称,只在该程序块中通用,在其他区域都无效也就是说,变量的名称从变量声明的位置开始,到包含该声明的程序块最后的大括号为止,这一区间内通用。这样的作用域称为块作用域
        而在函数外声明的变量标识符,其名称从声明的位置开始,到该程序的结尾都是通用的。这样的作用域称为文件作用域

(5)声明与定义

#include <stdio.h>
#define NUMBER 5                 /*学生人数 */int tensu[NUMBER];              /*数组定义*/int top(void);                 /*函数top的函数原型声明*/
int main()
{extern int tensu[];int i;printf("请输入%d名学生的分数。\n",NUMBER);for (i = 0; i < NUMBER; i++){printf("%d: ", i + 1);scanf("%d", &tensu[i]);}printf("最高分 = %d\n", top( ));return 0;
}
int top(void)
{extern int tensu[];        /*数组的声明(可以省略)*/int i;int max = tensu[0];for (i = 1; i < NUMBER; i++)if (tensu[i] > max)max = tensu[i];return max;
}

<1>  编译器在读取数据时,也是按照从头到尾的顺序依次读取的。因为本程序中函数top的函数定义在main函数后,所以要想在main函数中调用top函数,编译器就需要知道函数top是什么。因此需要使用第七行的声明(函数top无需参数,并且会返回int型的值)。
        像这样明确记述了函数的返回类型,以及形参的类型和个数等的声明称为函数原型声明。
        需要注意的是该声明要以分号结尾。
        函数原型声明只声明了函数的返回值和形参等相关信息,并没有定义函数的实体。

 <2>  21行开始就是top函数的定义声明,包含函数体,是对函数的定义。

        另外,如果函数top的需求(返回值的类型和形式参数等)发生了改变,那么函数定义和函数原型声明两部分都必须进行修改。
但是,在编写程序的时候,如果把函数top的函数定义放在main函数之前,就不用特意使用函数原型声明了。

三、多维数组作参数

接收多维数组的函数,可以省略相当于开头下标的n维的元素个数。但是,(n - 1)维之下的元素个数必须使用常量。
下面是接收一维数组~三维数组的参数的声明示例:

void funcl(int v[ ],int n);                  /*元素类型为int、元素个数随意(n)。*/
void func2(int v[ ][3], int n);              /*元素类型为int[3]、元素个数随意(n)。*/
void func3(int v[ ][2][3],int n) ;       /*元素类型为int [2] [3]、元素个数随意(n)。*/

所接收的数组的元素类型必须固定,但元素个数是自由的。

四、函数的嵌套调用和链式访问

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。

1、嵌套调用

函数可以嵌套调用,但是不能嵌套定义。下面代码就是主函数main调用three_line()函数,three_line()函数内调用new_line()函数。

#include <stdio.h>
void new_line()
{
printf("hello world\n");
}
void three_line()
{int i = 0;
for(i=0; i<3; i++){new_line();}
}
int main()
{
three_line();
return 0;
}

2、链式访问

链式访问就是把A函数的返回值作为B函数的参数。

void A()
{
    /*函数体*/
}
void B()
{
    A();
}
int main()
{
    B();
}

#include <stdio.h>
int main()
{printf("%d\n", printf("%d\n", printf("%d\n", 43)));return 0;
}

 五、函数的递归与迭代

1、函数递归

一个过程或函数在其定义或说明中有直接或间接调用自身的编程技巧称为递归。递归的主要思想在于:把大事化小。从字面意思可以理解为重复“递推”和“回归”的过程,当“递推”到达底部时就会开始“回归”。
递归的两个必要条件
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。

2、函数迭代

从初始状态开始,每次迭代都更新状态,多次迭代直到到达结束状态。说白了迭代就是一个循环,从初始值进入,不断的计算变化成新的值,最后在末状态输出。

3、举例

//递归法求n的阶乘
int factorial1(int n)
{if (n <= 1)return 1;elsereturn n * factorial1(n - 1);
}//迭代法求n的阶乘
int factorial2(int n)
{int result = 1;while (n > 1){result *= n;n -= 1;}return result;
}int main()
{int n = 5;printf("%d\n", factorial1(n));printf("%d\n", factorial2(n));
}

今天的分享就到这啦😉


如果我的文章对您有帮助,

请 “点赞” “收藏” “关注” 一键三连哦!

想了解更多知识请前往故里♡927的博客

如果以上内容有什么问题,欢迎留言,大家一起学习,共同进步。


我们下期见😉~~

这篇关于【C语言必经之路——第6节】函数内容总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/243226

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注