目录
1.函数:
1.能够让程序模块化
2.可以减少重复性代码
1.函数的三种形式:
1.函数的定义:
函数类型 函数名(数据类型1 形参1, 数据类型2 形参2, ...)
{
函数体;
return 返回值;
}
函数名:和变量名要求保持一致
函数类型:函数运行结果的类型(如果返回值类型与函数类型不一致,会将返回值强制类型 转换成函数类型返回)
不写函数类型默认为int类型
如果没有返回值,函数类型应该为void类型
返回值:函数的运行结果
形参:形式参数(做个样子)
注意:
函数没有返回值,return后面什么都不写
2.函数的调用:
函数名(实参1, 实参2, ...);
注意:
1.实参个数必须与形参个数一致,并一一对应
2.实参可以是常量、变量、表达式
3.实参与形参类型不一致时,会将实参强制类型转换为形参类型,传入函数中
4.函数调用时会发生传参的过程(实参将值传递给形参)
3.函数的声明:
声明和定义的区别:
1.声明:声明一个已经存在的变量或函数
2.定义:定义一个之前不存在的变量或函数,需要开辟新的空间
注意:
被调函数在主调函数下方定义,需要声明该函数
2.变量的作用域和生存周期:
1.作用域:
变量能够使用的范围
1.局部变量:
局部变量作用域在离定义该变量最近的大括号内
2.全局变量:
全局变量作用域在整个文件中
2.生存周期:
变量从开始被创建,到空间被回收的整个过程
3.变量的存储类型:
存储类型 数据类型 数组名;
int a;
1.自动型存储(局部存储)(默认存储类型)
auto
auto int a;
int a;
将变量存放到栈区中:
1.未经初始化值为随机值
2.代码执行到变量定义时为变量开辟空间
3.超过变量的作用域回收变量空间
2.静态存储
static
static int a;
将变量存放到数据区中:
1.未经初始化前值为0值
2.编译时为变量开辟空间
3.代码执行结束回收变量空间
除了修饰静态变量,还有2个功能:
1.限定变量的作用域只能在本文件中使用
2.可以防止多个文件中的全局变量重名
3.寄存器存储:
register
register int a;
优先存放到CPU内部的寄存器中,如果寄存器存满了,等价于auto存放在栈区中
4.外部存储:
extern
extern int a;
声明一个变量或函数是在外部存储的
作业:
1.封装三个函数
函数1:封装函数实现传入一个年份,判断该年为闰年还是平年?
int IsLeepYear(int year);
函数2:封装函数实现传入年、月、日,获得该天是该年的第几天?
int GetDayOfYear(int year, int month, int day);
函数3:封装函数实现传入年、月、日,获得该年剩余多少天?
int GetLeftDayOfYear(int year, int month, int day);
2.封装一个函数,给定一个数,判断该数是否为素数
int IsPrimeNum(int num);
4.函数传参:
1.值传递:
实参将值传递给形参,形参是实参的副本,对形参做的操作,实参不会受影响
函数体内部想使用函数体外部变量值的时候可以使用值传递
函数体内想修改函数体外部变量的时候不能使用值传递
2.全局变量传递:
3.整形数组的传递:
int a[5];
1.形式1:
int fun(int array[5]);
2.形式2:
int fun(int array[], int len);
在调用函数的时候数组不能写 [ ],如 int fun (array);直接写数组名即可。
4.注意:
1.形式1只能操作5个元素的数组,形式2可以操作不同类型长度的数组
2.函数体内部的数组会随函数结束被回收,如果后续还想操作该数组必须在外部定义传到函 数中
3.数组传递中,形参操作和实参操作的是同一个数组
练习:封装三个函数实现对数组的操作:
int InputArray(int array[], int len);
int BubbleSortArray(int array[], int len);
int OutputArray(int array[], int len);
4.字符型数组和字符串的传递
char str[32] = {"hello world"};
int fun(char str[]);
练习:封装一个函数实现strlen的功能
int MyStrlen(char str[]);
封装一个函数实现strcpy的功能
int MyStrcpy(char dst[], char src[]);
5.递归函数
1.函数定义时调用函数本身
注意:
1.递归一定要有结束条件
2.避免深层次的递归
练习:封装一个函数获得斐波那契数列的第n项的值(使用递归实现)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 ..
int Fun(int n);
6.预处理命令:
1.宏定义:
#define
只是代码的替换
1.不带参宏
#define PI 3.1415926
#define M 50
2.带参宏(宏函数)
带参宏与函数的区别:
1.函数有参数类型、返回值、传参的概念
2.带参宏没有参数类型、返回值、传参的概念
3.带参宏是在程序编译阶段加载到程序中
带参宏可能改变运算符的优先级,记得加括号
4.函数是在程序运行阶段加载到程序中
5.带参宏会使代码体积增大
6.函数不会使代码体积增大
7.带参宏执行效率高
8.函数执行效率低
2.头文件包含
#include <stdio.h>
在预处理阶段将stdio.h头文件展开到文件中
在/usr/include目录下查找stdio.h
#include "stdio.h"
在当前目录下查找stdio.h,如果当前目录找不到则在系统目录/usr/include目录下查找头文件
头文件以.h结尾:
1.头文件中存放宏定义
2.头文件中存放声明的全局变量和全局函数
3.头文件中存放自定义的数据类型
项目工程根据功能划分成不同的文件
jisuanqi ------- main.c 主函数的实现
|--- add.h add.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- add.c 加法相关的函数接口的实现
|--- sub.h sub.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- sub.c 减法相关的函数接口的实现
|--- mul.h mul.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- mul.c 乘法相关的函数接口的实现
|--- div.h div.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- div.c 除法相关的函数接口的实现
jisuanqi--------src ----- main.c 主函数的实现
| |--- add.c 加法相关的函数接口的实现
| |--- sub.c 减法相关的函数接口的实现
| |--- mul.c 乘法相关的函数接口的实现
| |--- div.c 除法相关的函数接口的实现
|
|----include ---- add.h add.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- sub.h sub.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- mul.h mul.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
|--- div.h div.c中用到的数据类型的定义、宏定义、全局变量的声明、全局函数的声明
3.条件编译:
#if 0
#elif 0
#endif
#ifndef 宏名
如果没有定义后面的宏则将后续代码加入编译中
#ifdef 宏名
如果定义后面的宏则将代码加入编译中
head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#endif
作业:
1.封装一个函数实现strlen的功能
int MyStrlen(char str[]);
封装一个函数实现strcpy的功能
int MyStrcpy(char dst[], char src[]);
封装一个函数实现strcat的功能
int MyStrcat(char str1[], char str2[]);
封装一个函数实现strcmp的功能
int MyStrcmp(char str1[], char str2[]);
2.封装一个函数获得两个数的最大公约数
封装一个函数获得两个数的最小公倍数