注:转载请标明原文出处链接:https://xiongyiming.blog.csdn.net/article/details/105418890
1 函数概述
函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。C语言中的函数相当于其它高级语言的子程序。
为什么需要函数?
(1) 避免重复性操作;
(2) 有利于程序的模块化;
什么是函数?
(1) 逻辑上:能够完成特定功能的独立的代码块
(2) 物理上:
能够接收数据,也可以不接受数据;
能够对接收的数据进行处理;
能够将数据处理的结果返回,也可以没有返回值;
2 函数定义
函数的一般形式为:
函数返回值的类型 函数的名字(函数的形参列表)
{
函数的执行体
}
代码示例
#include<stdio.h>
#include<iostream>
//定义函数
void f()
{
printf("我是一个函数,哈哈哈\n");
}
int main()
{
f();//调用函数
system("pause");
return 0;
}
运行结果
3 函数的返回值
函数的返回值是指函数被调用之后,执行函数体中的程序段所取得的并返回给主调函数的值。
函数的返回值只能通过 return 语句返回主调函数
return 表达式的含义:
(1) 终止函数并向主调函数返回表达式的值;
(2) 如果return表达式为空,则终止函数并不向被主调函数返回任何值;
(3) return是用来终止函数,而break用来终止循环和switch;
例如:
void f()
{
return ;//用来终止函数并不向主调函数返回任何值
}
int f()
{
return 0;// 终止被调函数,并向主调函数返回表达式的值
}
注: 函数返回值的类型也称为函数类型,如果函数名前的返回值类型和函数执行体中的return表达式中的类型不同的话,则最终函数返回值的类型以函数名前的返回值类型为准。
代码示例
#pragma warning( disable : 4996)
#include<stdio.h>
#include<iostream>
//定义无参函数且无返回值
void f1()
{
printf("我是一个无参函数且无返回值,哈哈哈\n");
}
//定义无参函数且无返回值
int f2()
{
printf("我是一个无参函数,且有返回值,哈哈哈\n");
return 0;
}
//定义有参函数且无返回值
void f3(int i)
{
printf("我是一个有参函数且无返回值,啦啦啦\n");
}
//定义有参函数且有返回值
int f4(int i)
{
printf("我是一个有参函数且有返回值,啦啦啦\n");
return i + 1;
}
int main()
{
f1();//调用无参函数
f2();
printf("------------------------------------\n");
int a = 10;
int b;
printf("a=%d\n", a);
f3(a);//调用有参函数
b = f4(a); //调用有参函数
printf("返回值为%d\n",b);
system("pause");
return 0;
}
运行结果
4 函数分类
函数可以分为:
- 有参函数 和 无参函数
- 有返回值函数 和 无返回值函数
- 库函数 和 自定义函数
- 普通函数 和 主函数(main函数)
- 值传递函数 和 地址传递函数
注意事项:
- 一个程序有且只有一个主函数;
- 主函数可以调用普通函数,普通函数不能调用主函数;
- 普通函数可以相互调用;
- 主函数是程序的入口,也是程序的出口;
函数调用和函数定义的顺序
- 如果函数调用写在函数定义前面,则必须加函数声明;
- 如果函数调用写在函数定义后面,可以不加函数声明;
函数声明
- 告诉编译器将可能出现的若干个字母代表一个函数;
- 告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况;
- 对库函数的声明通过 #include<库函数所在文件夹的名字.h> 来实现的
- 函数声明是一个语句,末尾必须加分号;
5 形参和实参
形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。
实参出现在主调函数中,进入被调函数后,实参变量也不能使用。
形参和实参的功能是作数据传送。
发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。
函数的形参和实参的特点:
- 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。
- 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。
- 实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配的错误。
- 函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
代码示例
#pragma warning( disable : 4996)
#include<stdio.h>
#include<iostream>
int f(int i)
{
i = i + 1;
printf("调用函数时输出i=%d\n",i);
return 0;
}
int main()
{
int a = 100;
printf("调用函数前a=%d\n", a);
printf("------------------------\n");
f(a);//调用函数
printf("调用函数后a=%d\n", a);
system("pause");
return 0;
}
运行结果
6 变量的作用域和存储方式
变量可分为:
- 按作用域分:全局变量和局部变量;
- 按变量的存储方式:静态变量、自动变量和寄存器变量;
全局变量: 在所有函数外部定义的变量称之为全局变量。
全局变量的使用范围: 从定义位置开始到整个程序结束。
局部变量: 在一个函数内部定义的变量或函数的形参都称之为局部变量。
局部变量的使用范围: 只能在本函数内部使用
注:全局变量和局部变量命名冲突问题
在一个函数内部,如果定义的局部变量的名字和全局变量名一样时,局部变量会屏蔽掉全局变量。
代码示例
#pragma warning( disable : 4996)
#include<stdio.h>
#include<iostream>
int f()
{
int number = 10;
number = number + 1;
printf("局部变量 number=%d\n", number);
return 0;
}
int main()
{
int number = 100;
printf("全局变量 number=%d\n", number);
f();
printf("全局变量 number=%d\n", number);
system("pause");
return 0;
}
运行结果