前言: 在探索编程世界的浩瀚星图中,C语言无疑是一颗璀璨夺目的星辰,它不仅奠定了现代计算机编程语言的基础,更是无数软件与系统背后的基石。自其诞生以来,C语言以其高效、灵活、接近硬件的特性,赢得了开发者们的广泛青睐与深厚情感。而在这门语言的浩瀚海洋中,函数(Function)则是航行者手中的罗盘与风帆,指引着代码的方向,驱动着程序的运行
函数,作为C语言中最基本也是最强大的构建块之一,它不仅仅是一段可以重复使用的代码集合,更是模块化编程思想的集中体现。通过定义函数,我们能够将复杂的任务分解成一系列简单、易于理解和维护的子任务,这不仅提高了代码的可读性和可维护性,还促进了代码的重用,使得软件开发过程更加高效有序
在本文中,我们将踏上一场关于C语言函数的探索之旅,揭开其神秘面纱,一窥其内部结构与工作原理。我们将从函数的基本概念出发,逐步深入到函数的定义、声明、调用以及参数传递等核心知识点,通过生动的例子和详细的解析,帮助读者构建起对C语言函数全面而深刻的理解
让我们一同踏上这段充满挑战与收获的C语言函数之旅吧!
库函数是将一些常用到的函数编完放到一个文件(通常是库文件,如lib文件)里,供其他人或程序进行调用的方式。这些函数一般是编译器提供的,可以在C源程序中直接调用。库函数极大地方便了用户,同时也补充了C语言本身的不足

C语言常用的库函数:

库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件
推荐一个C/C++查询库函数的网址:库函数

自定义函数是编程中非常重要的一个概念,它允许程序员根据自己的需求创建特定的函数来执行一系列操作或计算。这些函数可以在程序中多次调用,提高了代码的重用性和可维护性,给程序员一个很大的发挥空间
函数的组成:
ret_type fun_name(para1, * )
{
......;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数我们来简单定义几个函数
函数定义代码示例:
//获取最大值函数的设计
int get_max(int x, int y)
{
return (x > y) ? (x) : (y);
}
int main()
{
int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2);
printf("max = %d\n", max);
return 0;
}// 实现数据交换的函数
// 实现成函数,但是不能完成任务
void Swap1(int x, int y)
{
// 这里涉及到函数的形参,当需要修改变量的值的时候,我们在数据传输中,需要传递它的指针
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
//正确的版本
void Swap2(int* px, int* py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int num1 = 1;
int num2 = 2;
Swap1(num1, num2);
printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
Swap2(&num1, &num2);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
return 0;
}形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效
上面 Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。在main函数中传给 Swap1 的 num1 ,num2 和传给 Swap2 函数的 &num1 , &num2 是实际参数

内存分配

这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝
函数的调用是编程中的一个基本操作,它涉及到执行已经定义好的函数代码块。在调用函数时,程序会暂停当前执行点的代码,跳转到被调用函数的开始处执行,执行完毕后再返回到调用点继续执行后续的代码
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参
写一个函数判断一年是不是闰年 代码示例 (C语言):
// 写一个函数判断一年是不是闰年
int is_leap_year(int year)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int year = 0;
scanf("%d", &year);
if (is_leap_year(year) == 1)
{
printf("%d是闰年\n", year);
}
else
{
printf("%d不是闰年\n", year);
}
return 0;
}写一个函数,每调用一次这个函数,就会将 num 的值增加1 代码示例 (C语言):
// 写一个函数,每调用一次这个函数,就会将 num 的值增加1
void add_num(int* num)
{
(*num)++;
}
int main()
{
int num = 0;
for (int i = 0; i < 10; i++)
{
add_num(&num);
printf("num: %d\n", num);
}
return 0;
}函数的嵌套调用和链式访问是编程中常见的两种概念,它们在不同的编程语言和上下文中有着不同的表现形式,但核心思想都是为了提高代码的可读性和复用性
代码示例 (C语言):
void test1()
{
printf("hehe\n");
}
void test2()
{
int i = 0;
for (i = 0; i < 3; i++)
{
test1();
}
}
int main()
{
test2();
return 0;
}注意:函数可以嵌套调用,但是不能嵌套定义
链式访问:把一个函数的返回值作为另外一个函数的参数
代码示例 (C语言):
#include <string.h>
int main()
{
char arr[20] = "hello";
int ret = strlen(strcat(arr, "world"));
// strlen用于计算字符串的长度,遇到'\0'停止, 头文件是string.h
// strcat用于将两个字符串连接起来 头文件是string.h
printf("%d\n", ret);
return 0;
}int main()
{
printf("%d", printf("%d", printf("%d", 43))); // 4321
return 0;
}注意:printf函数的返回值是打印在屏幕上字符的个数
在编程中,函数的声明(Declaration)和定义(Definition)是两个相关但不同的概念,它们共同支持函数的使用。这两个概念在不同的编程语言和上下文中可能有所差异,但基本概念是相似的
代码示例 (C语言):
// test.h
int Add(int x, int y);
// test.c
#include "test.h"
int main()
{
printf("%d\n", Add(1, 2));
}
//函数Add的实现
int Add(int x, int y)
{
return x + y;
}函数递归是一种在函数中调用自身来解决问题的编程技术。递归通过将问题分解成更小的、更易于解决的子问题,直到达到一个基本的、无需递归即可解决的边界情况(称为基准情况或基本情况)。递归函数必须有一个或多个基准情况,以避免无限递归调用导致的栈溢出错误
接受一个整型值(无符号),按照顺序打印它的每一位 代码示例 (C语言):

// 接受一个整型值(无符号),按照顺序打印它的每一位
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}编写函数不允许创建临时变量,求字符串的长度 代码示例 (C语言):
int Strlen(const char* str)
{
// 递归出口
if (*str == '\0')
return 0;
// 统计数据
else
return 1 + Strlen(str + 1);
}
int main()
{
char* p = "abcdef";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}求n的阶乘 代码示例 (C语言):
int factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
int main()
{
printf("%d\n", factorial(5));
return 0;
}求第n个斐波那契数

代码示例 (C语言):
int fib(int n)
{
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main()
{
printf("%d\n", fib(10));
return 0;
}但是我们在使用这两个递归函数时,当数据过大时,特别耗费时间,且有可能程序会崩溃,其实是有许多重复的步骤让代码冗余
代码示例 (C语言):
int count = 0;//全局变量
int fib(int n)
{
if (n == 3)
count++;
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main()
{
printf("%d\n", fib(20));
printf("count: %d", count);
return 0;
}
在输出第20位斐波那契数时,就调用了2584次第3位斐波那契数
解决办法:
static 对象替代nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层所访问注意:
非递归斐波那契代码示例:
int fib(int n)
{
int result;
int pre_result;
int next_older_result;
result = pre_result = 1;
while (n > 2)
{
n -= 1;
next_older_result = pre_result;
pre_result = result;
result = pre_result + next_older_result;
}
return result;
}
int main()
{
printf("%d\n", fib(10));
return 0;
}在结束这篇关于C语言函数的介绍文章之际,我们不禁感慨于C语言作为编程基石的深远影响与强大功能。函数,作为C语言程序设计的核心构件之一,不仅极大地提升了代码的可读性、可维护性和重用性,还为我们解决复杂问题提供了模块化、结构化的思维方式
通过深入学习C语言中的函数定义、声明、调用以及参数传递等关键概念,我们不仅能够编写出更加高效、清晰的代码,还能逐步培养出良好的编程习惯和问题解决能力。从简单的输入输出函数到复杂的算法实现,每一个函数的编写与调用都是对编程技艺的一次锤炼与提升
更重要的是,C语言函数的学习为我们后续探索更高级、更专业的编程语言和技术领域打下了坚实的基础。无论是面向对象的程序设计、系统级编程还是嵌入式系统开发,对函数的理解和应用都是不可或缺的一部分
让我们在掌握C语言函数的基础上,继续保持对编程的热情与好奇心,勇于探索未知,不断挑战自我!!!
希望本文能够为你提供有益的参考和启示,让我们一起在编程的道路上不断前行! 谢谢大家支持本篇到这里就结束了,祝大家天天开心!