C语言:函数

本文详细介绍了C语言中的函数概念,包括库函数的使用、标准库与头文件、自定义函数的语法、形参和实参的关系、return语句的注意事项、数组作为函数参数、嵌套调用、链式访问以及函数的声明与定义,还特别讲解了static和extern关键字在不同情况下的作用。
摘要由CSDN通过智能技术生成

目录

一、函数的概念

二、库函数

(一)标准库和头文件

(二)库函数的使用方法

(三)使用

(四)库函数文档的一般格式

1.函数原型

2.函数功能介绍

3.参数和返回类型说明

4.代码举例

5.代码输出

6.相关知识链接

三、自定义函数

(一)语法形式

(二)使用

四、形参和实参

(一)概念理解

(二)形参和实参的关系

1.代码运行时的过程关系

2.在空间地址上的的关系

五、return语句

(一)注意事项

1.return后面可以是一个数值,也可以是一个表达式,也可以什么都没有。

2.若return返回的值,与函数返回类型不一致,系统则隐式转换return返回的值为函数的返回类型。

3.return语句执行后,函数彻底返回,程序不再执行。

4.如果函数中存在 if 等分支语句,则需要保证每种情况下都有return返回,否则导致编译错误。

六、数组做函数参数

(一)数组传参的注意事项

1.函数的形参和实参个数要匹配

2.形参如果是一堆数组,则数组的大小可以省略不写

3.形参若是二维数组,行能省略,但列不行

4.数组传参,形参不会创建新的数组。形参操作的数组和实参的数组是同一个数组。

七、嵌套调用

八、链式访问

(一)举一个简单的例子:

(二)再看一个例子:

九、函数的声明和定义

(一)在使用函数时,要先声明后调用。

(二)函数可以嵌套调用,但不能嵌套定义。

(三)多个文件

(四)static 和extern

1.extern

2.static

(1)修饰局部变量

(2)修饰全局变量

(3)修饰函数


一、函数的概念

我们在生活中见过函数的概念,如一元一次函数y = kx+b。

C语言也引入函数的概念,有些翻译为“子程序”。

C语言的程序其实是由无数个小的函数组合而成。一个函数如果能够完成某项特定任务的话,这个函数可以复用的,能够提升开发软件的效率。

简而言之,C语言的函数就是一个完成某项特殊任务的一小段代码。

        在C语言中,我们一般会见到两类函数,一种是库函数,一种是自定义函数。

二、库函数

(一)标准库和头文件

C语言标准中规定了C语言的各种语法规则,但不提供库函数。

C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库。不同的编译器厂商根据ANSI提供的C语言标准给出一系列函数的实现,这些函数就叫做库函数。

printf、scanf等都是库函数,库函数也是函数。这些函数是现成的,我们可以直接使用,在一定程度上提升了效率。

        C/C++官方链接C 标准库头文件 - cppreference.com

(二)库函数的使用方法

(三)使用

(四)库函数文档的一般格式

1.函数原型

2.函数功能介绍

3.参数和返回类型说明

4.代码举例

5.代码输出

6.相关知识链接

三、自定义函数

(一)语法形式

  • ret_type 是函数返回类型,有时候可以使用void来表示什么都不返回
  • fun_name 是函数名
  • 括号中放的是形式参数
  • {}括起来的是函数体

(二)使用

        写⼀个加法函数,完成2个整型变量的加法操作。

根据实际需要来设计函数,函数名、参数、返回类型都是可以灵活变化的,上面只是一个例子。

四、形参和实参

(一)概念理解

使用中的函数参数分为两类:实际参数和形式参数,分别简称实参和形参。

以上面的例题为例子:第一个{}中的a和b 是形式参数;第二个{}中调用Add函数时传递给Add函数的a和b,为实际参数。

只有在Add函数被调用的过程中,为了存放实参传递过来的值,形式参数才向内存申请空间。

(二)形参和实参的关系

1.代码运行时的过程关系

调用函数:需要写参数,但形参的名字可以命名。以上面的题为例子:

当代码读到 int c = Add_(a , b ),便开始调用Add函数,向空间申请内存,将a 和 b 的值拷贝一份,存放在Add_(      )函数中。代码执行后,返回 x + y 的值。

2.在空间地址上的的关系

值得一提的是, a 、 b 的地址与 x 、y 的地址,不一样。它们各自有自己的空间,自己的地址。

因此可以理解为,形式参数 x 和 y ,只是 a 和 b 的一份临时拷贝;就连地址,也只是暂时存在的。

五、return语句

(一)注意事项

1.return后面可以是一个数值,也可以是一个表达式,也可以什么都没有。

        若是表达式,则先执行表达式,再返回表达式的结果。

        若是什么都没有,则适合函数返回类型是void的情况。

2.若return返回的值,与函数返回类型不一致,系统则隐式转换return返回的值为函数的返回类型。

3.return语句执行后,函数彻底返回,程序不再执行。

4.如果函数中存在 if 等分支语句,则需要保证每种情况下都有return返回,否则导致编译错误。

六、数组做函数参数

(一)数组传参的注意事项

1.函数的形参和实参个数要匹配

2.形参如果是一堆数组,则数组的大小可以省略不写

3.形参若是二维数组,行能省略,但列不行

4.数组传参,形参不会创建新的数组。形参操作的数组和实参的数组是同一个数组。

七、嵌套调用

以解决“某一年某月有多少天”的问题来实践嵌套调用。

八、链式访问

链式访问,就是将一个函数的返回值作为另一个函数的参数,像链条一样把函数串联起来。

(一)举一个简单的例子:

如果将 strlen 的返回值作为 printf 的返回值,又会如何呢?

而这,就是一个链式访问的例子了:

(二)再看一个例子:

会打印出什么呢?

其实,这个例子的难点在于 printf 的返回值。

printf 函数返回的是打印在屏幕上的字符的个数。

在上面的代码中,第一个prinf打印的是第二个printf的返回值,第二个printf打印的是第三个printf的返回值。

第三个printf打印43,屏幕上的字符数量为2,返回2;

第二个printf打印2,屏幕上的字符数量为1,返回1;

第一个printf打印1

屏幕上最终打印:4321

九、函数的声明和定义

(一)在使用函数时,要先声明后调用。

上面的 int is_leap_year(int y) 就是函数的声明。如果将 int main() 与 int is_leap_year(int y)  调换位置,编译器可能会发出警告。因为编译器对代码进行编译的时候,是自上到下进行的。

(二)函数可以嵌套调用,但不能嵌套定义。

(三)多个文件

代码较多时,我们根据程序的功能,将代码拆分放在多个文件当中。

一般情况下,函数的声明、类型的声明放在头文件(.h), 函数的实现放在源文件(.c)当中。

但是也可以拆分放在三个文件当中,这样我们写代码就更加方便了。

(四)static 和extern

static 和extern 都是C语言的关键字。

在了解它们之前,我们先来了解一下作用域生命周期

作用域:

        程序设计概念。通常来说,一段程序代码中的所用到的名字并不总是有效(可用)的。而限定这个名字的可用性的代码范围,就是这个名字的作用域。

  • 局部变量的作用域就是变量所在的局部范围
  • 全局变量的作用域就是整个工程(项目)

生命周期:

        是指变量创建(申请内存)到变量销毁(收回内存)的一个时间段。

  • 局部变量的生命周期:进入作用域变量创建,生命周期开始,出作用域生命周期结束
  • 全局变量的生命周期:整个程序的生命周期

1.extern

exturn 是用来声明外部符号的。

如果⼀个全局的符号在A文件中定义,在B文件中想使用,就可以使用extern 进行声明。然后就可以使用了。

2.static

static是静态的意思,可以用来:

  • 修饰全局变量
  • 修饰局部变量
  • 修饰函数
(1)修饰局部变量

图一                                                                          图二

对比图一和图二的代码运=运行效果,来理解static在局部变量中的作用

        图一:test函数中的局部变量 i ,是每次进⼊test函数先创建变量(生命周期开始)并赋值为0,然后 ++,再打印,出函数的时候变量生命将要结束(释放内存)。

        图二:从输出结果来看,i 的值有累加的效果。用static 修饰局部变量 i ,在i创建好后,出函数的时候是不会销毁的,重新进入函数也不会重新创建变量,直接从上次累积的数值继续计算。

        结论:static改变了变量的生命周期。因此,未来⼀个变量出了函数后,如果我们还想保留值,等下次进入函数继续使用,就可以使用static 修饰。

那么,static 究竟是如何改变变量的生命周期的呢?

        其实,生命周期的改变,本质上是变量的存储类型的改变。一个局部变量最初是存储在栈区的,经过static修饰之后,便存储到了静态区。一旦存储在静态区,变量的生命周期就和全局变量的生命周期一样了:只有程序结束,变量才被销毁,内存才收回。

        但值得注意的是,即使变量被存储到了静态区,它的作用域仍不变。

(2)修饰全局变量

add.c                          add.c

       

text.c                          text.c

 

代码一                           代码二

运行结果:代码一正常,代码二出现链接性错误。

结论:一个全局变量被static修饰后,只能在本源文件中中使用,不能在其他源文件中使用。

本质原因

全局变量被默认为具有外部链接属性,想在外部的文件中使用,只需要适当的声明即可。

但是全局变量被static修饰之后,外部链接属性就变成了内部链接属性,就只能在自己所在的源文件内使用了。在其他源文件声明,也无法使用。

值得一提的是,全局变量具有的外部链接属性具有一定的不安全性,只要声明就能够使用。

因此,一个全局变量,只想在所在的源文件内使用,不想被其他文件发现,可以用static修饰。

(3)修饰函数

add.c                                      add.c 

                       

text.c                                       text.c

           

代码一                           代码二

运行结果:代码一正常,代码二出现链接性错误。

结论: static 修饰函数和 static 修饰全局变量是一样的,⼀个函数在整个工程都可以使用, 被static修饰后,只能在本文件内部使用,其他文件无法正常的链接使用。

本质原因:

函数默认具有有外部链接属性,使得函数在整个工程中只要被适当的声明就能够被使用。

但被static修饰后,函数就具有了内部链接属性,使得函数只能在所在的源文件内部使用。

因此,一个函数只想在所在的源文件内使用,不想被其他源文件使用时,可以用static来修饰。

到这里就结束了,如有后续会继续补充。

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值