目录
0 前言
1 定义函数
2 调用函数
3 函数的实参和形参
4 函数声明
5 作用域
5.1 局部变量和全局变量
5.2 static关键字
5.2.1 修饰局部变量
5.2.2 修饰全局变量
5.2.3 修饰函数
6 函数的返回值
6.1 return语句
6.2 函数返回值的类型
7 函数的其他形式
7.1 函数作为表达式
7.2 函数作为实参
0 前言
函数是组织好的、可重复使用的、用于执行指定任务的代码块。函数是 C 语言程序实现模块化思想的关键。
在C语言中函数分为以下两种:
(1)库函数:由系统或第三方库提供,直接调用即可,无需了函数内部实现,例如printf、getchar 等函数
(2)用户自定义函数:由程序员手动封装,需要了解函数内部实现 以上两种函数都是程序中比较常用的,一般情况下,如果系统库已经提供了实现某个功能的函数,直接 调用系统库函数即可,否则用户需要自己编写代码实现
1 定义函数
return_type function_name( parameter list ){body of the function}
返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型,有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void
函数名称(function_name):这是函数的实际名称。函数名和参数列表一起构成了函数签名
参数(parameter):参数就像是占位符,当函数被调用时,您向参数传递一个值,这个值被称为 实际参数,参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包 含参数
函数主体:函数主体包含一组定义函数执行任务的语句
无参无返回值函数的定义
void print()
{printf("我是一个无返回值无参数的函数");
}
有参数无返回值函数的定义
void sum(int a, int b)
{printf("a+b=%d", a + b);
}
有参数有返回值函数的定义
int mul(int a, int b)
{return a * b;
}
定义函数注意事项:
(1)同一个.c 文件中,函数名之间不能重名
(2)用户自定义函数一般需要放置在调用它的函数之前,如果放置在调用它的函数之后就需要添加函数声明
(3)函数之间不能嵌套定义,也就是说函数内部不能再定义函数
2 调用函数
定义了函数之后,我们可以通过函数名()的方式来调用,如果函数有参数调用的时候还需要传入参数:函数名(参数1,参数2),如果函数有返回值我们还可以接收函数的返回值
注意: 定义函数的时候需要定义到 main函数上面,如果定义到main函数下面需要进行声明
详细看4 函数声明
#include <stdio.h>
void print()
{printf("我是一个无返回值无参数的函数\n");
}void sum(int a, int b)
{printf("a+b=%d\n", a + b);
}int mul(int a, int b)
{return a * b;
}int main()
{print();sum(10, 20);int c = mul(2, 4);printf("c=", c);return 0;
}
3 函数的实参和形参
形参: 就是函数定义时函数名后面小括号中的变量,本质上就是局部变量,在该函数被调用时,由外部为该形参变量进行赋值,形参变量与局部变量的生命周期是一样的,只能在本函数内使用,函数执行结束形参变量就被释放,需要注意的是,形参只能是变量
实参:调用函数的时候实际传入的数据就是函数的实参
#include <stdio.h>
void sum(int a, int b) // 形参
{printf("a+b=%d\n", a + b);
}
int mul(int a, int b) // 形参
{return a * b;
}
int main()
{sum(10, 20); // 实参int a = 2;int b = 3;int c = mul(a, b); //实参printf("c=", c);return 0;
}
4 函数声明
注意: 定义函数的时候需要定义到 main函数上面,如果定义到main函数下面需要进行声明
当把函数定义到main函数下面的时候,默认main函数里面是无法调用这个函数的
#include <stdio.h>
int main()
{int a = 2;int b = 3;int c = mul(a, b); // 实参printf("c=%d", c);return 0;
}
int mul(int a, int b) // 形参
{return a * b;
}
此代码会提示: main.c:8:13: warning: implicit declaration of function 'mul' [ Wimplicit-function-declaration]
如果想把自定义函数定义到main函数下面,我们就需要声明函数
#include <stdio.h>
// 声明函数
int mul(int a, int b);
int main()
{int a = 2;int b = 3;int c = mul(a, b); // 调用函数printf("c=%d", c);return 0;
}
// 定义函数
int mul(int a, int b)
{return a * b;
}
5 作用域
5.1 局部变量和全局变量
局部变量:定义在函数内部的变量被称为局部变量。局部变量只能在当前函数中访问,不能跨函数访问,函数执行结束时,局部变量将被系统回收
全局变量: 全局变量是指在整个程序中都可见的变量。它们可以被任何函数调用并使用。全局变量通常在程序开始时声明,并在程序执行期间保持不变,即使它们的作用域已经消失。虽然全局变量可以提高 程序的可重用性和可扩展性,但它们也可能会带来一些潜在的问题,如命名冲突和安全问题
#include <stdio.h>
int x = 2; // 全局变量
int sum()
{int a = 10; // 局部变量int b = 20;printf("a=%d", a);printf("b=%d", b);printf("b=%d", x); // 正确
}
int main()
{sum();// printf("a=%d", a); // 错误 局部变量只能在作用域内访问printf("a=%d", x); // 正确return 0;
}
5.2 static关键字
5.2.1 修饰局部变量
当 static 修饰局部变量时,该变量被称为静态局部变量。其主要作用如下:
1.延长变量的生命周期:普通局部变量存储在栈区,在函数调用结束后就会被销毁;而静态局部变量存储在静态存储区,在程序的整个运行期间都存在,不会因为函数调用结束而被销毁。
2.保持变量的值:静态局部变量只会在第一次函数调用时进行初始化,之后再次调用该函数时,静态局部变量会保留上一次调用结束时的值。
#include <stdio.h>void test() {// 静态局部变量,只会在第一次调用函数时初始化static int count = 0;count++;printf("count = %d\n", count);
}int main() {test();test();test();return 0;
}
代码解释:
在 test
函数中,count
是一个静态局部变量。第一次调用 test
函数时,count
被初始化为 0,然后自增为 1 并输出;第二次调用 test
函数时,count
不会再次被初始化为 0,而是保留上一次的值 1,然后自增为 2 并输出;同理,第三次调用时输出 3。
5.2.2 修饰全局变量
当 static
修饰全局变量时,该变量被称为静态全局变量。其主要作用是限制变量的作用域,使该变量只能在定义它的源文件中使用,而不能被其他源文件通过 extern
关键字引用
// file1.c
#include <stdio.h>
// 静态全局变量,只能在 file1.c 中使用
static int staticGlobalVar = 10;void printStaticGlobalVar() {printf("staticGlobalVar = %d\n", staticGlobalVar);
}
// file2.c
// 尝试在另一个源文件中使用静态全局变量,这是错误的
// extern int staticGlobalVar; int main() {// 这里不能直接使用 staticGlobalVar// printf("staticGlobalVar = %d\n", staticGlobalVar);return 0;
}
代码解释:
在 file1.c
中定义了一个静态全局变量 staticGlobalVar
,它只能在 file1.c
文件中使用。在 file2.c
中,即使使用 extern
关键字声明,也无法引用该变量。
5.2.3 修饰函数
当 static
修饰函数时,该函数被称为静态函数。其主要作用也是限制函数的作用域,使该函数只能在定义它的源文件中使用,而不能被其他源文件通过 extern
关键字调用
// file1.c
#include <stdio.h>
// 静态函数,只能在 file1.c 中使用
static void staticFunction() {printf("This is a static function.\n");
}void callStaticFunction() {staticFunction();
}
// file2.c
// 尝试在另一个源文件中声明并调用静态函数,这是错误的
// extern void staticFunction(); int main() {// 这里不能直接调用 staticFunction// staticFunction();return 0;
}
在 file1.c
中定义了一个静态函数 staticFunction
,它只能在 file1.c
文件中被调用。在 file2.c
中,即使使用 extern
关键字声明,也无法调用该函数。
6 函数的返回值
按照有无返回值,函数可以分为无返回值函数和有返回值函数。对于无返回值函数前面已经介绍过,这类函数的返回值类型为 void
对于有返回值函数,需要显式指定的返回值类型这类函数的返回值通过 return 语句得到。 retum 是C语言中的关键字,后面可以跟常量、变量、表达式等。例如:
return 100; //返回常量 100
return a; //返回变量 a的值
return a + b; //返回表达式a+b 的运行结果
说明:retumn 语句后面可以加括号也可以不加,例如:
return (100); //返回常量 100
return (a); //返回变量 a的值
return (a+b); //返回表达式a+b 的运行结果
6.1 return语句
return语句的作用主要有以下两个:
(1)返回值:当函数执行到return 语句时,会将return 后面的结果值返回给主调函数,也就是说,在主函数中可 以得到被调函数中的数据
(2)终止程序:当return 语句被执行时,它下面的语句将不再执行。因此,retumn 语句可以看作是函数结束的标志,一般放置在函数末尾,以免影响其他语句的正常执行,return 还可以在无返回值的函数中作为终止函数使用
6.2 函数返回值的类型
函数返回值类型指的是函数返回数据的类型。例如:
char getChar();int getInt();float getFloat();double getDouble();void print();
以上5个函数的返回值类型分别为: 字符型、整型、单精度浮点型、双精度浮点型、无返回值型,当主调函数中需要得到被调函数的返回值时,也要定义与其函数返回值类型对应的变量进行接收
7 函数的其他形式
7.1 函数作为表达式
#include <stdio.h>
int sum(int a, int b)
{return a + b;
}
int main(void)
{int c = 100 + sum(10, 20);printf("c=%d\n", c);return 0;
}
7.2 函数作为实参
#include <stdio.h>
// 声明函数
int mul(int a, int b);
int main()
{int a = 2;int b = 3;printf("c=%d", mul(a, b));return 0;
}
// 定义函数
int mul(int a, int b)
{return a * b;
}