函数的基础概念
函数(function)
是C语言编程中的基本构建块之一。使用函数可以将代码模块化,提高代码的可读性和可维护性。函数允许程序员定义一次特定的操作,然后在程序的多个地方调用它。
在C语言中,函数的定义包含以下几个部分:
返回类型
:函数返回值的类型。
函数名
:函数的标识符。
参数列表
:函数的输入参数(可以为空)。
函数体
:包含执行语句的代码块。
比如最常见的主函数main()
:
/*
返回类型 函数名(参数列表) {函数体 // 比如:输出 Hello World返回值
}
*/
int main(void)
{printf("Hello World\n");return 0;
}
同时函数也分为有参数函数
和无参数函数
,比如:
定义一个无参数无返回值的函数用于打印文字
#include <stdio.h>// 定义函数
void sayHello()
{printf("Hello, World!\n");
}int main()
{// 调用函数sayHello();return 0;
}
定义一个有参数有返回值的函数来计算两个数值的和
#include <stdio.h>// 定义函数
int sumAB(int a, int b)
{return a + b;
}int main()
{int result;// 调用函数并存储返回值result = sumAB(5, 3);printf("两数之和为: %d\n", result);return 0;
}
声明函数
在C语言中,声明函数是告知编译器有关函数名称、返回类型以及参数类型的信息,而无需提供函数的实际实现(即函数体)。函数声明通常出现在程序的开头、在main函数之前,或者在头文件(.h文件)中,以便在多个源文件之间共享。
形式大概如下:
返回类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...);
举个例子:
#include <stdio.h>char GGBond(); // 声明一个char型函数
float GGBondLen(); // 声明一个浮点型函数
int GGBondAge(); // 声明一个整数型函数
void GGBondOhYeah(); // 声明一个无返回类型函数int main()
{printf("%c\n", GGBond());printf("GGBond的长度: %.2f\n", GGBondLen());printf("GGBond的年龄: %d\n", GGBondAge());GGBondOhYeah();
}char GGBond()
{return 'G';
}float GGBondLen()
{return 18.2;
}int GGBondAge()
{return 12;
}void GGBondOhYeah()
{printf("Oh Yeah! GGBond!!!\n");
}
在VS Code中可以看到结构
这组代码的运行结果如下
函数的返回类型
函数的返回类型指定了函数执行完毕后返回给调用者的值的类型。如果函数不返回任何值,则使用void类型。常见的返回类型包括int、float、double、char等,以及用户自定义的类型(如结构体、联合体等)
#include <stdio.h>// 返回int类型的函数
int getInteger() {return 42;
}// 返回float类型的函数
float getFloat() {return 3.14f;
}// 返回double类型的函数
double getDouble() {return 2.718281828459045;
}// 返回char类型的函数
char getChar() {return 'A';
}// 定义一个结构体类型
struct MyStruct {int x;float y;
};// 返回结构体类型的函数
struct MyStruct getStruct() {struct MyStruct s;s.x = 10;s.y = 20.5;return s;
}// 定义一个联合体类型
union MyUnion {int i;float f;
};// 返回联合体类型的函数
union MyUnion getUnion() {union MyUnion u;u.i = 100;// 注意:此时u.f的值是未定义的,因为i和f共享同一块内存return u;
}int main() {// 调用并打印返回int类型的函数printf("int类型函数: %d\n", getInteger());// 调用并打印返回float类型的函数printf("浮点类型函数: %.2f\n", getFloat());// 调用并打印返回double类型的函数printf("双精度浮点数类型函数: %.10f\n", getDouble());// 调用并打印返回char类型的函数printf("字符型函数: %c\n", getChar());// 调用并打印返回结构体类型的函数struct MyStruct s = getStruct();printf("结构体类型函数: x = %d, y = %.2f\n", s.x, s.y);// 调用并打印返回联合体类型的函数union MyUnion u = getUnion();// 注意:只打印i,因为f的值是未定义的printf("联合体类型函数: i = %d\n", u.i);return 0;
}
函数的指针
在C语言中,函数名实际上是一个指向函数首地址的指针,可以定义指向函数的指针,并通过这些指针调用函数。
#include <stdio.h>// 定义一个函数
int add(int a, int b)
{return a + b;
}int main()
{// 定义一个指向函数的指针int (*funcPtr)(int, int) = add;// 通过函数指针调用函数int result = funcPtr(5, 3);printf("两数之和为: %d\n", result);return 0;
}
函数的参数传递方式
C语言中的函数参数传递主要有两种方式:值传递
和指针传递
。
- 值传递:函数接收的是参数值的副本,对参数的修改不会影响原变量。
- 指针传递:函数接收的是参数的地址,通过指针可以直接修改原变量的值。
#include <stdio.h>void modifyValue(int x)
{x = 10;
}// 指针传递
void modifyPointer(int *x)
{*x = 10; // 修改的是原变量
}int main()
{int a = 5;modifyValue(a);printf("值传递后 a = %d\n", a); // 输出 a = 5modifyPointer(&a);printf("指针传递后 a = %d\n", a); // 输出 a = 10return 0;
}
函数的嵌套调用和链式调用
函数可以嵌套调用其他函数,也可以设计成链式调用的形式,以实现更复杂的逻辑。
#include <stdio.h>// 定义两个简单的计算函数
int square(int x)
{return x * x;
}int increment(int x)
{return x + 1;
}// 链式调用
int main()
{int num = 3;int result = square(increment(num)); // 先调用 increment,再调用 squareprintf("链式调用结果: %d\n", result); // 输出 16return 0;
}
静态函数和全局函数
- 静态函数:在函数前加上
static
关键字,该函数就只能在定义它的文件内部被调用,有助于避免命名冲突。 - 全局函数:没有
static
修饰的函数,可以在其他文件中通过声明(函数原型)后使用。
// test1.c
#include <stdio.h>// 静态函数,只能在 test1.c 中使用
static void localFunction()
{printf("这是一个静态函数\n");
}// 全局函数
void globalFunction()
{printf("这是一个全局函数\n");
}
// test2.c
#include <stdio.h>// 声明全局函数
extern void globalFunction();int main()
{// // localFunction(); 这一行是错误的,不能访问静态函数globalFunction(); // 访问全局函数return 0;
}
这段代码运行后会在终端输出:
这是一个全局函数