写在前面
- 库函数
- 特点:IDE已经定义和编译好的函数,源代码一般不可见
- 功能:标准头文件提供其原型,即声明,只需正确调用即可
- 函数
- 意义:函数和语句即为代码的基本单元
- 功能:用户可编写特定功能的函数,包括调用库函数
一、基本函数体
1.1 模板
- 示例:求两数乘积
#include <iostream> using namespace std; // 函数原型(声明) // 首double为返回值类型,括号内double为形参类型,即函数允许传入的参数类型 // 声明时变量名不是必须的,即x、y可省略 double cube(double x, double y); /**************************************************************/ int main() { // 局部变量区:代码块(即大括号)中或函数中定义的变量均为局部变量 double a = b = 3.14; // 函数调用 // a,b为实参,类型要与形参匹配,否则强制转换 // side类型需同函数return返回的类型一致 double side = cube(a, b); } /**************************************************************/ // 函数定义:伴随特定功能的实现,不可在语句块或函数体内 double cube(double x, double y) { // 函数返回值,复合数据类型建议返回指针 return x * y; }
1.2 特性
- 按值传参
- 传参本质
- 调用函数时:传递的参数是实参值的拷贝,类似
double x = a; double y = b;
- 传递后:x、y和a、b就互不相关了
- 调用函数时:传递的参数是实参值的拷贝,类似
- 返回值本质
- 通过return语句将函数值带回到临时内存块中,主调函数从中取出数据
- 随后形参单元及函数体的内存被释放销毁
- 传参本质
- 函数返回值
- 显式返回语句:return语句明确函数返回值
- 无返回值:可省略return语句,函数声明:
void cube(double x,y);
- 无传入参数:有return语句,函数声明:
double cube();
1.3 内联函数
- 特点:编译时将内联函数语句插入到所有调用位置,进而导致程序变大,但不一定总会加,看编译器,优点是运行快
- 示例:
// main外,声明(常规都是单语句),按值传递 inline double square(double x) { return x * x} // main内,调用 double num = square( 3.14 );
二、函数与数组
- 示例代码
#include <iostream> using namespace std; // 函数原型(声明):以下4选1 // 声明一:传入数组起始指针和结尾指针,在原数组上读写 void arr(int * begin, int * end); // 声明二:传入数组起始指针和结尾指针,函数内数组只读 void arr(const int * begin, const int * end); // 声明三:传入数组起始指针和元素个数,在原数组上读写 void arr(int * begin, int num); // 声明四;传入数组起始指针和元素个数,函数内数组只读 void arr(const int * begin, int num); /*********************************************/ int main(){ int week = {1,3,5,7}; // 数组的首地址:&week[4] // 数组首元素的地址:week或&week[0] int * pweek = week; // 对应声明:一、二 // 也可以局部传入arr(pweek, pweek+2) arr(pweek, pweek+4); // 对应声明:三、四 // 也可以局部传入arr(pweek, 2) arr(pweek, 4); } /*********************************************/ // 函数定义:无返回值,此处仅演示了声明二 void arr(const int * begin, int num) { for(int i = 0; i < num; i++) { // 可以begin++,但不可(*begin)++,因为const cout << *(begin + i) << endl; // 因为直接操作数组,所以没有返回值 } }
三、函数与字符串
- 字符串:
不
以空‘\0’
字符结尾的char数组
只是数组,不是字符串 - 示例(将字符串竖着输出)
#include <iostream> using namespace std; // 函数原型(声明) void fun(const char * pt); /******************************************/ int main() { // 声明及定义字符串指针pchar const char * pchar = "this is a bird"; // 函数调用 fun(pchar); } /******************************************/ // 函数定义 void fun(const char * pt) { // 功能:按字符扫描字符串,遇到尾部空字符退出 while(*pt) { cout << *pt<< endl; pt++; } }
四、函数与结构
- 按地址传递(点坐标操作)
#include <iostream> using namespace std; // 全局:结构声明、定义 struct point { int x; int y; }; // 函数原型需要在结构声明定义之后 void fun(const point * pt_in, point * pt_out); /**********************************************/ int main() { point pt_1 = { 3,4 }; point pt_2 = {}; fun(&pt_1, &pt_2); cout << pt_2.x << endl; } /**********************************************/ // 此处传递的是结构指针,pt_in只读,pt_out修改的是实参 void fun(const point * pt_in, point * pt_out) { cout << pt_in->x << endl; // 把pt_in的x坐标给pt_out的x坐标 pt_out->x = pt_in->x; }
- 按值传递(返回结构)
// 函数调用:这里就是对副本的操作了 point pt_3 = fun(pt_1); // 函数定义:返回结构 point fun(point pt_in) { point total = {}; total.x = pt_in.x; return total; }
五、存储类说明符
-
功能:存储说明符描述了存储的持续性、作用域和链接性
-
链接性:数据共享范围
- 内部性:只在当前文件内共享
- 外部性:在文件间共享,都必须声明,但只可定义一次
- 无链接性:只在代码块中可用
-
种类
关键字 特点 写法 auto 声明中自动类型判断,无链接性,只能定义局部变量,函数结束即销毁,通常不写 auto int mouth;
register 声明中指示寄存器存储,如计数器 register int mouth;
static a 修饰局部变量:在函数或语句块中定义的局部变量,程序生命周期中不销毁,内部性
b 修饰全局变量:限定作用域仅在当前文件,内部性static int mouth;
extern 引用式声明全局变量或函数:即声明引用在其他地方定义的变量,用于跨文件共享,只可定义一次,可声明多次,外部性 extern int mouth;
thread_local 变量的持续性与线程相同 -
常量声明
-
写法
// 所有函数体外声明:内部性链接 const int num = 10; // file1 所有函数体外声明:外部性链接 extern const int num = 10; // file2 只声明即可使用 extern const int num; // 函数体可直接调用变量num进行使用