【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节】函数内容总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/qq_64836447/article/details/128823371
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/243226

相关文章

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

Python函数返回多个值的多种方法小结

《Python函数返回多个值的多种方法小结》在Python中,函数通常用于封装一段代码,使其可以重复调用,有时,我们希望一个函数能够返回多个值,Python提供了几种不同的方法来实现这一点,需要的朋友... 目录一、使用元组(Tuple):二、使用列表(list)三、使用字典(Dictionary)四、 使

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi