最近偷懒了,迷上了三国和李贺。给大家分享一下最喜欢的一句诗:吾不识青天高黄地厚,唯见月寒日暖来煎人寿。我还不是很理解27岁的李贺,如何写出如此绝笔。
正文开始,今天我们来探讨一下关于C语言中的函数部分
max
函数)。sortArray
)直观理解功能,降低代码复杂度。返回类型 函数名(参数列表) {
// 函数体:实现具体功能
return 返回值; // 非void类型必须返回对应类型的值
}
示例:计算两数之和
int add(int a, int b) { // 返回int,参数a、b为int
return a + b; // 返回和
}
关于库函数和其他语言中封装的函数在上篇文章中已经讲到了,详情请看[从库函数到API接口,深挖不同语言背后的“封装”与“调用”思想-CSDN博客]()
标准库:C 语言内置的函数集合,分为:
stdio.h
):printf
(输出)、scanf
(输入)。string.h
):strlen
(字符串长度)、strcpy
(字符串复制)。math.h
):sqrt
(开平方)、pow
(幂运算)。stdlib.h
):malloc
(动态内存分配)、free
(释放内存)。头文件:包含库函数的声明
(告诉编译器函数的存在、参数和返回值)。使用库函数前必须包含对应头文件,例如:
#include // 包含printf的声明
int main() {
printf("Hello, World!"); // 调用库函数
return 0;
}
fgets
为例)查阅文档:fgets
从文件中读取字符串,原型为 char *fgets(char *s, int size, FILE *stream);
。
包含头文件:#include
(fgets
声明在此头文件中)。
调用函数
#include
int main() {
char str[100];
fgets(str, 100, stdin); // 从标准输入(键盘)读取最多99个字符(含'\0')
printf("输入内容:%s", str);
return 0;
}
注意事项:
size
参数需小于数组长度(避免缓冲区溢出)。NULL
表示读取失败(如文件结束)。void
:无返回值(如仅打印信息的函数)。int
、float
等):返回对应类型的值。void func()
或 func()
(C99 后允许省略 void
)。int add(int a, int b)
(a
、b
为形参,接收实参的值)。return
提前结束函数(void
函数用 return;
)。#include
#include
// 自定义函数:判断n是否为素数(返回1是,0否)
int isPrime(int n) {
if (n <= 1) return 0; // 1及以下不是素数
for (int i=2; i<=sqrt(n); i++) { // 优化:只需检查到平方根
if (n % i == 0) return 0; // 能整除,不是素数
}
return 1; // 是素数
}
int main() {
int num;
printf("输入一个整数:");
scanf("%d", &num);
if (isPrime(num)) {
printf("%d是素数\n", num);
} else {
printf("%d不是素数\n", num);
}
return 0;
}
n
接收实参(用户输入的 num
)。isPrime(num)
中的 num
)。isPrime(7)
)、变量(isPrime(num)
)、表达式(isPrime(2+3)
)。isPrime(int n)
中的 n
)。n
是 num
的拷贝,修改 n
不影响 num
)。// 交换两数(通过地址传递,修改实参)
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x=10, y=20;
swap(&x, &y); // 实参是x、y的地址(传递指针)
printf("x=%d, y=%d\n", x, y); // 输出x=20, y=10(实参被修改)
return 0;
}
*a
、*b
接收实参的地址(&x
、&y
),通过解引用(*a
)直接修改原变量的值。return a + b;
返回和)。void
函数中的 return;
,跳过后续代码)。void 函数
void printMessage() {
printf("Hello!\n");
return; // 可省略(函数体结束自动返回)
}
非 void 函数
int max(int a, int b) {
if (a > b) return a; // 返回a,结束函数
return b; // 必有一个执行(确保返回值)
}
错误处理
int divide(int a, int b) {
if (b == 0) {
printf("除数不能为0!\n");
return -1; // 错误码(调用者根据返回值判断是否出错)
}
return a / b;
}
数组名作为参数时,传递的是首元素的地址(即指针),函数内对数组的修改会影响原数组(因为操作同一块内存)。
语法
void printArray(int arr[], int size) { // 等价于int *arr
for (int i=0; i<size; i++) {
printf("%d ", arr[i]); // 等价于*(arr+i)
}
}
#include
void bubbleSort(int arr[], int size) {
for (int i=0; i<size-1; i++) {
for (int j=0; j<size-i-1; j++) {
if (arr[j] > arr[j+1]) { // 交换相邻元素
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main() {
int nums[] = {5, 3, 8, 1, 2};
int size = sizeof(nums) / sizeof(nums[0]); // 计算数组长度
bubbleSort(nums, size); // 传递数组名(首地址)和长度
for (int i=0; i<size; i++) {
printf("%d ", nums[i]); // 输出1 2 3 5 8(原数组已排序)
}
return 0;
}
size
),因为形参 arr
是指针(丢失长度信息)。void printHeader() {
printf("===== 欢迎使用系统 =====\n");
}
void printMenu() {
printHeader(); // 嵌套调用printHeader
printf("1. 登录\n2. 注册\n3. 退出\n");
}
int main() {
printMenu(); // 输出:===== 欢迎使用系统 ===== → 菜单选项
return 0;
}
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
int main() {
// 先算add(2,3)=5,再算mul(5,4)=20(链式调用)
int result = mul(add(2, 3), 4);
printf("结果:%d\n", result); // 输出20
return 0;
}
定义在前:直接调用(无需声明)。
定义在后:需先声明(告诉编译器函数存在)。
int add(int, int); // 声明(参数名可省略,只写类型)
int main() {
int res = add(3,5); // 调用时,编译器通过声明知道add存在
return 0;
}
int add(int a, int b) { return a + b; } // 定义在后
步骤:
创建头文件(func.h
):声明函数
#ifndef FUNC_H
#define FUNC_H
int add(int a, int b); // 声明
#endif
创建源文件(func.c
):定义函数
#include "func.h" // 包含头文件(双引号表示当前目录)
int add(int a, int b) { return a + b; } // 定义
主文件(main.c
):调用函数
#include
#include "func.h" // 包含头文件,获取声明
int main() {
printf("%d\n", add(3,5)); // 调用func.c中的add
return 0;
}
编译:需同时编译 main.c
和 func.c
(如 gcc main.c func.c -o main
)。
静态函数(static 修饰函数)
作用:仅当前文件可见(其他文件无法调用,避免命名冲突)。
示例(func.c
)
static int add(int a, int b) { return a + b; } // main.c调用会报错(未定义)
静态变量
静态局部变量(函数内)
生命周期为程序运行期(保留值,如计数器)。
void count() {
static int num = 0; // 第一次调用初始化,后续保留值
num++;
printf("第%d次调用\n", num);
}
// 调用:count() → 第1次,count() → 第2次(num保留1)
静态全局变量(文件内,函数外):仅当前文件可见(同文件内函数可访问,其他文件不可见)。