函数的定义
子程序,是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
库函数
函数分类
库函数
一些基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到,为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
C语言常用的库函数:
- IO函数
- 字符串操作函数
- 字符操作函数
- 内存操作函数
- 时间/日期函数
- 数学函数
- 其他库函数
注: 但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。这里对照文档来学习上面几个库函数,目的是掌握库函数的使用方法。
库函数查询工具:
- MSDN(Microsoft Developer Network)(不用网)
- www.cplusplus.com
- http://en.cppreference.com
自定义函数
自定义函数组成:
返回值类型 函数名(形参列表)
{
函数体;
}
#include <stdio.h>
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);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
return 0;
}
函数Swap1中仅仅交换了形参的值,而实参并没有改变。
函数Swap2中运用指针变量,解引用指针变量,使得指针变量所指向的实参值改变。这种传参方式称作按址传参。
函数参数
实际参数(实参):
真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配
内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在 函数中有效。
函数调用
传值调用:
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用:
1、传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
2、这种传参方式可以让函数和函数外边的变量建立起正真的联系,也就是函数内部可以直接操 作函数外部的变量
嵌套调用:
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0; i<3; i++)
{
new_line();
}
}
int main()
{
three_line();
return 0;
}
链式访问:
把一个函数的返回值作为另外一个函数的参数。
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
//结果是啥?
return 0;
}
为什么呢?
这里要从printf函数的返回值是什么意义说起。
printf返回一个int类型的值,表示被打印的数字的字符。
函数的声明和定义
函数声明:
- 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,无关紧要。
- 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
- 函数的声明一般要放在头文件中的。
函数定义:
- 函数的定义是指函数的具体实现,交待函数的功能实现。
#ifndef __TEST_H__
#define __TEST_H__
//函数的声明
int Add(int x, int y);
#endif //__TEST_H__
在头文件中,ifndef和endif的作用是预防头文件多次引用。
也可以用 #pragma once 头文件名 的方式来代替。
引用头文件方式:
- #include <stdio.h>这种只会去自带库中去找。
- #include "testh"这种会优先去自带库中找,随后在本地定义的头文件去找。
函数递归
定义:程序调用自身的编程技巧称为递归。
递归的两个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。
递归的基本思想
- 将大事情简化成小事情
- 处理大事情的方式与处理小事情的方式一致。
例子:
编写函数不允许创建临时变量,求字符串的长度。
#include <stdio.h>
int Strlen(const char*str)
{
if (*str == '\0')
return 0;
else return 1 + Strlen(str + 1);
}
int main()
{
char *p = "abcdef";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}
递归的特点:
- 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
- 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
- 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。