目录:
一:定义
函数是一组一起执行一个任务的语句
每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数
函数声明告诉编译器函数的名称、返回类型和参数
函数定义提供了函数的实际主体
二:函数的一般形式
return_type function_name( parameter list )
{
body of the function
}
组成部分
1.返回类型
- 返回类型:一个函数可以返回一个值
- return_type 是函数返回的值的数据类型
- 有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void
2.函数名称
- 函数名称:这是函数的实际名称
- 函数名和参数列表一起构成了函数签名
注意:
函数名和参数列表一起构成了函数签名
意味着可以出现参数列表不同但是函数名相同的函数。
void print()
{
printf("hello world!");
}
void print(int nums)
{
printf("%d\n",a);
}
这是合法的!!!
3.参数
- 参数:参数就像是占位符
- 当函数被调用时,您向参数传递一个值,这个值被称为实际参数
- 参数列表包括函数参数的类型、顺序、数量
- 参数是可选的,也就是说,函数可能不包含参数
4.函数主体
- 函数主体:函数主体包含一组定义函数执行任务的语句
实例:
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
该函数有两个参数 num1 和 num2,会返回这两个数中较大的那个数
三:函数声明
return_type function_name( parameter list );
补充:
在函数声明中,参数的名称并不重要,只有参数的类型是必需的
int max(int num1, int num2);
等价于
int max(int, int);
四:调用函数
当程序调用函数时,程序控制权会转移给被调用的函数
实例:
#include <stdio.h>
/* 函数声明 */
int max(int num1, int num2);
int main ()
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
/* 调用函数来获取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
运行结果:
Max value is : 200
由于程序是从上向下执行,所以函数要先声明,后调用
由于程序是从上向下执行,所以函数要先声明,后调用
五:函数参数
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。 |
引用调用 | 通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。 |
六:内部函数&外部函数&内联函数
根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数
内部函数又称静态函数
可以使函数的作用域只局限于所在文件
1.内部函数
定义:
如果一个函数只能被本文件中其他函数所调用,它称为内部函数
在定义内部函数时,在函数名和函数类型的前面加 static
static 类型名 函数名 (形参表)
2.外部函数
定义:
如果在定义函数时,在函数的首部的最左端加关键字 extern,则此函数是外部函数,可供其它文件调用
extern int max (int a,int b)
注意:如果在定义函数时省略 extern,则默认为外部函数
3.内联函数
定义:
内联函数是指用inline关键字修饰的函数
在类内定义的函数被默认成内联函数
内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质
内联扩展是用来消除函数调用时的时间开销
通常用于频繁执行的函数,对于小内存空间的函数非常受益
注意:
- 递归函数不能定义为内联函数
- 内联函数一般适合于不存在while和switch等复杂的结构且只有1~5条语句的小函数上,否则编译系统将该函数视为普通函数
- 内联函数只能先定义后使用,否则编译系统也会把它认为是普通函数
- 对内联函数不能进行异常的接口声明
七:main 函数的参数
main 函数其实与我们写的函数没有什么区别,它也会有自己的参数
1. main 函数带参数 :
int main( int argc, char *argv[] )
2.main函数没有参数:
int main()
3.argc 和 argv
argc 和 argv 是 main 函数的形式参数
这两个形式参数的类型是系统规定的
变量名称argc和argv是常规的名称,当然也可以换成其他名称
main 的两个参数的参数名如下:
int main( int argc, char *argv[] )
以写成下面这样:
int main( int test_argc, char *test_argv[] )
argc 是指传入参数的个数
argv[] 是一个指针数组,指向传递给程序的每个参数
4.如何传递给main函数的argc和argv的呢?
C程序在编译和链接后,都生成一个exe文件,执行该exe文件时,可以直接执行
也可以在命令行下带参数执行,命令行执行的形式为:
可执行文件名称 参数1 参数2 ... ... 参数n
可执行文件名称和参数、参数之间均使用空格隔开
命令行字符串将作为实际参数传递给main函数:
- (1) 可执行文件名称和所有参数的个数之和传递给 argc
- (2) 可执行文件名称(包括路径名称)作为一个字符串,首地址被赋给 argv[0],参数1也作为一个字符串,首地址被赋给 argv[1],... ...依次类推
八:函数参数传递都是值传递
本质上说,C 里面所有的函数参数传递,都是值传递
为什么?
因为指针传递之所以能改变传递参数变量的值,是因为 swap 函数交换的不是传递进来的指针本身,而是指针指向的值
实例:
void swap(int *x, int *y);
void swap(int *x, int *y){
int temp;
//这里操作的是指针指向的值 而不是指针
temp = *x;
*x = *y;
*y = temp;
// 倘若直接交换指针 a、b的值不会交换
// temp = x;
// x = y;
// y = temp;
}
int main( int argc, char *argv[] )
{
int a = 5;
int b = 10;
swap(a, b); //调用交换函数
printf("交换结果为 a = %d, b = %d\n",a,b);
return 0;
}