函数(入门——上篇)

目录:

1.函数是什么

2. 库函数

3. 自定义函数

4. 函数参数

5. 函数调用

6. 函数的嵌套调用和链式访问

7. 函数的声明和定义


序言.

  本文主要通过《明解C语言》和《C语言程序现代设计》两本书,对C语言函数知识进行一个简要的涵盖与总结.

一.函数是什么

 程序是由一个个小的零件组成的,而函数就是这种“零件”的一个较小的单位.

 在数学上,我们经常可能会听到函数的概念,但不同于数学上的函数,C语言中的函数不一定需要参数,也不一定需要计算数值,两者之间是有差别存在的.

 上图是来自维基百科的定义,在其中一大段话中,我们可以大致了解到函数的两大明显作用.

1.使我们的代码具备相对独立性

把需要重复的代码块单独封装成一个函数,这样可以使编程不会出现语句冗余的现象,大大增强了程序的可读性和编程的趣味性.

2.提供对过程的封装和细节的隐藏

在调用函数实现功能时,我们往往只需要提供参数,函数名即可,具体如何实现,真的可能未必知道,比如我们常用的printf函数,我们就不一定知道具体它是如何实现的,但我们可以调用它.

下图,也可以用类似电路图图形的方式展现给我们看求最大值的一个函数.

二.函数的分类

1. main函数和库函数

在C语言中,main函数作为程序的入口,是必不可少的.一旦程序运行,就会执行main函数的主体部分.

main函数中使用的printf,scanf,puts等等一系列函数,就是我们常称的库函数.C语言的基础库中提供了一系列类似的库函数,它们不是业务性的代码,但我们在开发的过程中每个程序员都可能用的到,通过提供这样的库函数,就能够大大提高代码的可读性和可移植性.

那怎么学习库函数呢?
这里我们可以简单的看看: www.cplusplus.com

想了解哪个函数,我们简单一搜,就能全部知道了.

简单的总结, C 语言常用的库函数都有:
IO函数
字符串操作函数
字符操作函数
内存操作函数
时间/日期函数
数学函数
其他库函数

这里来模拟一下strcpy这个库函数的实现,打开网站搜索,有如下结果

它的参数有两个,一个是指向destination的char *指针,一个是指向source的char *指针,发挥的作用是,将source指向的字符串内容拷贝到destination指向的字符串中,包括/0也一起拷过去. 

1.src指向的内容我们不需要它修改,按照cplusplus上的定义,加上const修饰,即便后面弄反dest,src,编译器也不会通过.

2.返回的是一个char*的指针,而不是void设计

3.assert函数报错,避免两者指针中有一个为空指针

4.将循环体并入循环条件中,直到src解引用后为/0,赋给*dest后,循环停止. 

2. 自定义函数

自定义函数和库函数一样,有函数名,返回值类型和函数参数.
但是不一样的是这些都是我们自己来设计,这给程序员一个很大的发挥空间
1.返回类型
函数返回的值—— 返回值的类型,在该函数的情况下,返回的是两个int型数值中较大的一个.无返回参数,则用void表示无返回值.
如下面的倒计时函数,就不需要返回任何参数,仅仅是执行一系列重复的printf语句.
同样的例子还有很多,比如printf函数会返回打印的字符个数,我们往往也对其不感兴趣, C语言中允许我们在函数前面加void,像(void)printf("hello\n"); 这条语句就不会有任何返回值,实际上是对“抛弃”的一种委婉说法.
2.函数名
函数的名称,从其它零件调用函数时,使用函数名.( 应尽量起一些具有实际意义的函数名,比如加法函数Add)
3.形参声明
用于接收辅助性提示的临时变量—— 形式参数的声明.如果含有多个,用逗号进行隔开.

同时一定记得函数名后加圆括号,否则就会报错. 

4.函数体
每个函数都有一个用花括号括起来的主体执行部分.

三.函数的参数

1.实参

真实传给函数的参数,叫实参.
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
参.

2.形参

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
存单元),所以叫形式参数.
形式参数当函数调用完成之后就自动销毁了.(具体细节请参照函数栈帧创建与销毁篇章)因此形式参数只在函数中有效.
注意: 形参和实参是可以同名的,但两者并不在一个空间,并且一旦出了函数,形参会立即销毁!
形参实例化之后其实只相当于实参的一份临时拷贝而已!!!

四.函数的调用

为了了解函数,函数的定义和函数的调用都是必不可少的,前者时站在设计者的角度,后者则是站在使用者的角度.

1.传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参

2.传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式.
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量.
//实现两个数的交换
void Swap1(int x, int y) 
{
 int tmp = 0;
 tmp = x;
 x = y;
 y = tmp;
 }

void Swap2(int *px, int *py) 
{
 int tmp = 0;
 tmp = *px;
 *px = *py;
 *py = tmp;
 }
int main()
{
 int num1 = 1;
 int num2 = 2;
 Swap1(num1, num2);//传值调用,无法进行交换两个数的操作
 printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
 
 Swap2(&num1, &num2);//传址调用,通过解引用指针,访问变量num1,num2的空间
 printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
 return 0; 
}

五.函数的嵌套调用和链式访问

1.嵌套调用

顾名思义,在函数中调用另一个函数,main函数中使用printf函数实际上也是函数的嵌套调用.

2.链式访问

 把一个函数的返回值作为另外一个函数的参数

这里strcat返回的指针,提供给strlen函数,然后strlen函数计算字符串的长度,这里我们还模拟实现strcpy函数,当然只是其中一种模拟实现my_strcpy函数的方式.

六.函数的声明和定义

1.函数声明

PS:若未指定函数返回值, 默认返回int类型,即编译器为函数创建了一个 隐式声明.

 像上述average函数,如果放在main函数之后,不会报错,但它会默认返回值是一个int类型,直到运行到后面发现是double类型,于是会报错.

解决这个问题的方法就是函数声明

函数声明能够使编译器先对函数进行概要浏览,而函数定义可以之后再给出.

 在main函数前加上这条,那main函数就知道average函数返回的值是double类型.

总结:(函数声明的作用)
 
 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数
 声明决定不了.
 函数的声明一般出现在函数的使用之前。要满足 先声明后使用.
  函数的声明一般要放在头文件中的.

2.函数的定义

函数的定义是指函数的具体实现,交待函数的功能实现.
我们要学会模块式写代码,使代码更加具有结构性.
test.h 的内容   放置函数的声明
#ifndef __TEST_H__
#define __TEST_H__
//函数的声明
int Add(int x, int y);
#endif //__TEST_H__
test.c 的内容   放置函数的实现
#include "test.h"
//函数Add的实现
int Add(int x, int y) {
 return x+y; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值