任何事物都不如习惯那样强有力。
-
函数
-
概念
用于封装一个功能的代码集合
-
优点
1.便于使用
2.降低耦合度
3.提高复用率
4.保护内部
-
分类
-
1.库函数
由系统或其他三方提供的函数,无需自定义直接使用
如:
strlen
strcpy
malloc
...
-
2.系统调用
由系统提供的可以直接访问内核的函数
-
3.自定义函数
自己定义函数并调用
注意:
库函数与系统调用的函数无需定义,直接调用
使用步骤
1.定义
语法:
返回值类型 函数名(形参列表)
{
函数体
}
返回值类型:返回值的数据类型
函数名:自定义标识符
形参列表:可有可无,声明多个局部变量,多个直接使用逗号分开
函数体:要封装的代码
关键字:
void:空类型,在函数的返回值类型使用,表示该函数没有返回值
return:结束当前函数,函数体使用
注意:
1.return xxx ; xxx就是返回值
2.一个函数体只能有一个返回值
3.函数只定义不调用其中的代码不会执行
2.调用
位置:在函数中调用
语法1:
函数名(实参列表);
语法2:
变量名 = 函数名(实参列表);
注意:
只能应用与返回值的函数
接收的变量的数据类型要与函数的数据类型一致
注意:
调用函数时的实参列表要与被调用的函数的形参列表列表要一致(长度一致,顺序一致,数据类型一致)
练习
案例1:定义一个函数,计算10+15的结果
#include <iostream>
using namespace std;
//定义一个无参无返回值的方法
void fun01()
{
int a = 10;
int b = 15;
int x = a + b;
cout << "x=" << x << endl;
}
int main(int argc, char const *argv[])
{
//调用无参无返回值的函数
fun01();
//每次调用函数时都会执行一次被调用的函数体中的代码
fun01();
return 0;
}
案例2:定义一个函数,计算两数之和
#include <iostream>
using namespace std;
//定义一个有参函数与调用
void add(int a,int b)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
int x = a + b;
cout << x << endl;
}
int main(int argc, char const *argv[])
{
add(1,11);
int num01 = 12;
int num02 = 3;
add(num01,num02);
int n1 = 0;
int n2 = 0;
cin >> n1 >> n2;
add(n1,n2);
return 0;
}
案例3:定义一个函数,计算两数之差,并返回结果
#include <iostream>
using namespace std;
int sub(int x,int y)
{
int n = x - y;
return n;
}
void test(int x,int y)
{
int n = x - y;
}
int main(int argc, char const *argv[])
{
//调用有返回值的函数,可以不接收返回值
sub(10,2);
int x = 0;
//调用有返回值的函数,可以接收返回值
x = sub(1,2);
cout << x << endl;
//调用无返回值的函数,不能接收返回值
test(1,2);
//int y = test(1,2);
return 0;
}
案例4:通过年龄判断是否成年
#include <iostream>
using namespace std;
int isCN(int age)
{
if (age >= 18)
{
return 0;
}
return -1;
}
int main(int argc, char const *argv[])
{
int tag = isCN(2);
cout << tag << endl;
return 0;
}
-
声明
-
直接声明
语法
extern 返回值类型 函数名(形参列表);
注意:声明时可以忽略形参列表中的变量名不写
示例
//06_code.cpp
#include <iostream>
using namespace std;
//声明一个无参函数
extern void fun01();
//声明一个有参的函数
extern void fun02(int a,int b);
//声明函数时可以忽略形参的变量名不写
extern void fun03(int,int);
//声明其他文件的函数
extern void fun04();
int main(int argc, char const *argv[])
{
fun01();
fun02(1,2);
fun03(1,2);
fun04();
return 0;
}
void fun01()
{
cout << "fun01" << endl;
}
void fun02(int a,int b)
{
cout << "fun02" << endl;
}
void fun03(int a,int b)
{
cout << "fun03" << endl;
}
//06_test.cpp
#include <iostream>
using namespace std;
void fun04()
{
cout << "fun04" << endl;
}
注意:多个文件参与,编译时需要将多个文件同时编译成一个可执行文件
编译的命令:
g++ 源文件名1 源文件名2 .... -o 生成可执行文件名
如:
g++ 06_code.cpp 06_test.cpp
注意
全局函数可以在其他源文件中使用
-
间接声明
在头文件中声明
示例
//07_test.cpp
#include <iostream>
using namespace std;
void fun01()
{
cout << "07_test.cpp" << endl;
}
void add(int a,int b)
{
cout << (a+b) << endl;
}
void sub(int a,int b)
{
cout << (a - b) << endl;
}
void mul(int a,int b)
{
cout << (a * b) << endl;
}
void del(int a,int b)
{
cout << a / b << endl;
}
//07_test.h
extern void fun01();
extern void add(int,int);
extern void sub(int,int);
extern void mul(int,int);
extern void del(int,int);
//07_code.cpp
#include <iostream>
#include "07_test.h"
using namespace std;
int main(int argc, char const *argv[])
{
fun01();
return 0;
}
注意
编译时无需编译头文件
-
特殊情况
多重调用
在函数A中使用函数B,在函数B中使用函数C
重载
同一程序中函数名相同,形参列表不同
递归
在函数中调用函数本身
调用过程
大量调用函数会发生"出入栈"的开销
案例1:定义一个函数,传入变量a,将a的值修改为10,在主函数中打印,查看结果,并分析原因
案例2:定义一个函数,传入数组nums,将nums中下标为0的值修改为10,在主函数中打印数组nums下标查看结果,分析原因
案例3:定义一个函数传入字符串,改变第一个字符
#include <iostream>
using namespace std;
void fun(char str[])
{
str[0] = 'H';
}
int main(int argc, char const *argv[])
{
char s[] = "hello";
fun(s);
cout << s << endl;
return 0;
}
-
变量存储
-
内存分配
进程
一个正在运行的程序,是程序从开始到结束的一个过程
程序是一个文件
每一个进程都对应一个空间
32位平台,每个进程最大不超过4GB
从0x00 00 00 00 ~ 0xff ff ff ff 结束
这片区间可分为
堆区 动态内存申请,在堆里开辟内存
栈区 所有的局部变量
全局区 静态变量(static),全局变量
常量区 常量或const修饰的变量
代码区 二进制指令
-
普通局部变量
定义位置:函数中
定义语法:
数据类型 变量名 = 值;
作用范围:当前的{}之间
生命周期:当前{}结束,局部变量就释放
内存区域:栈区
注意:
局部变量不初始化时内容随机
示例
void test01()
{
int num1 = 10; //局部变量
{
int num1 = 20;
printf("num1 = %d\n", num1); //就近原则 20
}
printf("num1 = %d\n", num1); // 10
}
-
普通全局变量
定义位置:函数外
定义语法:
数据类型 变量名 = 值;
作用范围:当前源文件以及其他源文件都可以识别
生命周期:整个进程,进程结束时全局变量才会被释放
内存区域:全局区
注意事项:
1.全局变量不初始化时内容为0
2.全局变量和局部变量同名,优先选择局部变量
3.如果使用其他源文件的全局变量,请加extern声明
示例
int num1 = 10; //全局变量
void test02()
{
int num1 = 20;
printf("num1 = %d\n", num1); //就近原则 20
}
-
静态局部变量
定义位置:函数中
定义语法:
static 数据类型 变量名 = 值;
作用范围:只有在{}语句中有效
生命周期:整个进程,进程结束时才会释放
内存区域:全局区
注意:
1.静态局部变量遇到重复定义时,只有第一次定义有效
2.静态局部变量不初始化内容为0
示例
void test03()
{
static int num;
printf("num = %d\n", num);
num++;
}
int main()
{
test03();
test03();
test03();
test03();
return 0;
}
-
静态全局变量
定义位置:函数外
定义语法:
static 数据类型 变量名 = 值;
作用范围:只能当前源文件使用
生命周期:整个进程,进程结束时才会释放
内存区域:全局区
注意:
1.静态全局变量不初始化时内容默认值为0
2.只能在当前源文件使用,不能跨文件使用
示例
static int num = 100;//静态全局变量
int main(int argc, char const *argv[])
{
printf("num = %d\n", num);
return 0;
}