目录
一、库函数
1.标准库和头文件
标准库:C语言的国际标准ANSI规定的一些常用函数的标准
库函数:不同编译器厂商根据ANSI提供的C语言标准,给出的一系列函数的实现
2.库函数的使用
先包含头文件,再调用函数!
3.库函数的学习
可以检索C语言标准库的网址: cplusplus.com - The C++ Resources Network
库函数文档的格式:
(1)函数原型
(2)函数功能
(3)函数参数以及返回值
(4)代码举例
(5)代码输出
(6)相关知识链接
二、自定义函数
1.函数的创建及调用
函数创建
数据类型 函数名(形式参数){函数体}
//eg.加法函数
//int add(int x, int y){return x+y;}
函数调用
函数名(形式参数);
//eg.加法函数调用
//add(2, 3);
//最终返回结果为5
2.函数的参数
形参与实参
1.函数不调用,形参不向内存申请空间
2.函数调用时,实参将值传递给形参
3.形参是实参的一份临时拷贝,改变形参不会影响实参的值
注:传参分为值传递、地址传递(指针部分提到)和引用传递(C++语法),想通过形参改变实参的值只能通过后两种方法!
#include<stdio.h>
//值传递
void swap1(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
//地址传递
void swap2(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main()
{
int a = 1;
int b = 9;
swap1(a, b);
printf("a=%d b=%d\n", a, b);//a=1 b=9
swap2(&a, &b);
printf("a=%d b=%d\n", a, b);//a=9 b=1
return 0;
}
数组作参数
1.实参为数组:形参不创建新数组,而是与实参共用同一数组(本质上为地址传递,指针部分会详细讲到)
2.形参为数组:一维数组可省略大小;二维数组可省略行,不可省略列
#include<stdio.h>
//打印一维数组
void Print1(int arr[], int size)//arr[10]和arr[]等价
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//打印二维数组
void Print2(int arr[][3], int size)//不可省略arr[][3]的“3”
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < size; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int size1 = sizeof(arr1) / sizeof(arr1[0]);
Print1(arr1, size1);//输出:1 2 3 4 5 6 7 8 9 10
int arr2[][3] = { {1,2,3},{2,3,4},{3,4,5} };
int size2 = sizeof(arr2[0]) / sizeof(arr2[0][0]);
Print2(arr2, size2);
//输出:1 2 3
// 2 3 4
// 3 4 5
//
return 0;
}
3.返回值
return语句
1.返回类型为void: 直接写return;或不写return
2.形参为void: 不需要传参数(强行传实参会报错)
3.如果没有写返回类型,会默认为int
4.非void类型,每个分支必须含return
#include<stdio.h>
void test01(void)
{
printf("666\n");
}
//比较两个整形
int cmp(int x, int y)
{
if (x > y)
{
return 1;
}
//x <= y的情况无返回值
}
int main()
{
int a = 3;
test01(a);//强行传参数a,报警告
cmp(4, 5);//无返回值,报警告
return 0;
}
补充:printf的返回值为输出字符个数
#include<stdio.h>
int main()
{
int a = printf("987\n");//输出字符'9' '8' '7' '\n'四个字符,返回值为4
printf("%d\n", a);//输出4
return 0;
}
4.作用域和生命周期
作用域
1.局部变量:变量所在的局部范围
2.全局变量:整个工程
生命周期
1.局部变量:进入作用域变量创建,生命周期开始,出作用域生命周期结束
2.全局变量:整个程序的生命周期
5.模块化编程
模块化编程含义
对于一个函数,通常包含函数声明、函数定义和函数调用三个部分
#include<stdio.h>
int add(int x, int y);//函数声明
int main()
{
int a = add(3, 4);//函数调用
printf("%d\n", a);//输出:7
return 0;
}
int add(int x, int y)//函数定义
{
return x + y;
}
在实际工程中,我们会用到许多函数模块,为了方便使用,通常将函数声明和函数定义分开。函数声明放在头文件(.h)中,函数定义放在源文件(.c)中。
模块化编程好处
1.逻辑清晰:所有函数声明都分模块写在头文件中,相应功能一目了然,便于使用
2.方便协作:团队合作时,不同成员同时负责不同函数模块功能,最后通过头文件(.h)包含汇总。但若全写在一个文件中,则需等前一个成员写完后,下一个成员才能开始,效率低下
3.方便代码隐藏:如果想将自己的函数给别人使用,又不想让他知道具体怎么实现的,可以通过传静态库(.lib)和头文件(.h)
6.static和extern
extern
声明外部函数或变量
/***********************test.c*******************/
int a = 1;
int add(int x,, int y)
{
return x + y;
}
/**********************main.c*******************/
#include<stdio.h>
extern int a;
extern int add(int x, int y);
int main()
{
a = add(3, 5);//若没有上面两个extern会报错
printf("%d", a);//输出:8
return 0;
}
static
1.修饰局部变量:作用域不变,生命周期变长
2.修饰全局变量:作用域变小,外部链接属性——>内部链接属性(不可用extern声明)
3.修饰函数:作用域变小,外部链接属性——>内部链接属性(不可用extern声明)
#include<stdio.h>
void test(void)
{
static int k = 0;
k++;
printf("%d ", k);
}//k为static修饰,函数调用结束后也不销毁
int main()
{
for (int i = 0; i < 5; i++)
{
test();
//printf("%d", k);//k的作用域仍然为test函数,k未声明报错
}
//输出:1 2 3 4 5;
return 0;
}
static修饰局部变量本质:将局部变量存储到静态区,成为静态变量
最后,感谢大家观看!