内联函数(Inline Function)是编译器优化建议,建议将函数代码直接展开到调用点,避免函数调用开销。
特点:
inline关键字只是建议,编译器可忽略static inline组合在头文件中使用,避免多重定义递归(Recursion)是函数调用自身的编程技巧。
递归三要素:
尾递归优化:
嵌入式中的风险:
// 内联函数定义
inline 返回类型 函数名(参数列表) {
// 函数体
}
// static inline(头文件中使用)
static inline 返回类型 函数名(参数列表) {
// 函数体
}
// 递归函数示例
int factorial(int n) {
if (n <= 1) return 1; // 终止条件
return n * factorial(n-1); // 递归调用
}
#include <stdio.h>
#include <time.h>
// 内联函数示例
static inline int max_inline(int a, int b) {
return (a > b) ? a : b;
}
// 普通宏(有副作用问题)
#define MAX_MACRO(a, b) ((a) > (b) ? (a) : (b))
// 递归:阶乘
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// 递归:斐波那契数列(普通递归,效率低)
int fibonacci_naive(int n) {
if (n <= 0) return 0;
if (n == 1) return 1;
return fibonacci_naive(n - 1) + fibonacci_naive(n - 2);
}
// 尾递归:斐波那契
int fibonacci_tail(int n, int a, int b) {
if (n == 0) return a;
if (n == 1) return b;
return fibonacci_tail(n - 1, b, a + b);
}
// 递归:二分查找
int binary_search(int arr[], int left, int right, int target) {
if (left > right) return -1;
int mid = left + (right - left) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target)
return binary_search(arr, mid + 1, right, target);
else
return binary_search(arr, left, mid - 1, target);
}
int main() {
// 内联函数测试
printf("max_inline(3, 5) = %d\n", max_inline(3, 5));
// 宏的副作用问题
int x = 3, y = 5;
printf("MAX_MACRO(x++, y) = %d\n", MAX_MACRO(x++, y));
printf("After MAX_MACRO: x = %d\n", x); // x被递增两次!
// 递归:阶乘
printf("\n5! = %d\n", factorial(5));
printf("10! = %d\n", factorial(10));
// 递归:斐波那契
printf("\nFibonacci(10) = %d\n", fibonacci_naive(10));
printf("Fibonacci(10) tail = %d\n", fibonacci_tail(10, 0, 1));
// 递归:二分查找
int arr[] = {1, 3, 5, 7, 9, 11, 13, 15};
int size = sizeof(arr) / sizeof(arr[0]);
int target = 7;
int idx = binary_search(arr, 0, size - 1, target);
printf("\nBinary search %d: index = %d\n", target, idx);
return 0;
}
编译命令:
gcc -Wall -Wextra -O2 -o inline_recursive inline_recursive.c
./inline_recursive
inline建议(如函数体过大、含循环等)MAX_MACRO(x++, y)会导致x递增两次,内联函数不会Q1: inline函数和宏有什么区别? A: inline是函数,有类型检查、作用域、调试信息;宏是文本替换,有副作用风险。inline更安全,但编译器可能不内联。
Q2: 什么是尾递归?为什么能优化? A: 尾递归是递归调用作为函数最后操作。编译器可将其优化为循环,复用当前栈帧,避免栈增长。
Q3: 递归和迭代如何选择? A: 递归代码更简洁(如树遍历),但有栈开销。迭代效率更高。嵌入式系统优先考虑迭代。
Q4: 如何避免递归栈溢出? A: 1) 确保递归深度有限 2) 使用尾递归 3) 改为迭代 4) 增大栈空间(嵌入式有限)
Q5: static inline在头文件中的作用?
A: static确保每个编译单元有自己的副本,避免链接时多重定义错误。inline建议编译器内联展开。