函数是C语言中代码复用的基本单元。它封装了一段可重复调用的代码块,接收输入参数并可返回结果。
函数的组成要素:
void表示无返回值形参与实参:
函数调用栈帧:
// 函数定义
返回类型 函数名(参数列表) {
// 函数体
return 返回值; // 非void函数必须return
}
// 函数声明(原型)
返回类型 函数名(参数类型1, 参数类型2, ...);
// 函数调用
函数名(实参1, 实参2, ...);
#include <stdio.h>
// 函数声明(原型)
int add(int a, int b);
void print_message(const char *msg);
double calculate_average(int arr[], int size);
int main() {
// 函数调用
int result = add(10, 20);
printf("10 + 20 = %d\n", result);
print_message("Hello, Function!");
int scores[] = {85, 92, 78, 95, 88};
double avg = calculate_average(scores, 5);
printf("Average: %.2f\n", avg);
return 0;
}
// 函数定义
int add(int a, int b) {
return a + b;
}
void print_message(const char *msg) {
printf("%s\n", msg);
}
double calculate_average(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return (double)sum / size;
}
编译命令:
gcc -Wall -Wextra -o function_basics function_basics.c
./function_basics
Q1: 值传递和引用传递的区别? A: C语言只有值传递。传指针本质上也是值传递(传递指针的副本),但可以通过指针修改原数据。C++才有真正的引用传递。
Q2: 函数调用时栈帧是如何变化的? A: 调用时:压入参数→压入返回地址→保存旧EBP→分配局部变量。返回时:释放局部变量→恢复EBP→弹出返回地址→跳转继续执行。
Q3: 为什么需要函数原型? A: 函数原型让编译器在调用前知道函数的签名(返回类型、参数类型),可以进行类型检查,并确保调用方式正确。
Q4: 数组作为函数参数时,sizeof得到的是什么? A: 数组退化为指针,sizeof得到的是指针大小(32位系统4字节,64位系统8字节),而非数组总大小。因此必须额外传递数组长度。
Q5: 函数可以返回数组吗? A: C语言不能直接返回数组。可以返回指向数组的指针(但不能返回局部数组的指针),或使用结构体包装数组。