Linux基础学习笔记8(C语言基础:函数递归、预处理指令)

一、函数递归(Recursion)

1. 概念

递归:函数自己调用自己,属于一种特殊的循环方式。

2. 递归的两大注意点(必须掌握)

(1)必须有“结束条件”
没有结束条件 → 无限递归 → 最终导致:

Segmentation fault (core dumped)

原因:递归每进入一次都会申请一段栈空间,栈空间耗尽就崩溃(栈空间一般8M大小)。
(2)避免递归层次过深

例如:①fib(50) ②深度特别大的DFS 等等问题会导致调用栈过大。

3. 递归的应用场景

(1)回溯法(八皇后、全排列)
(2)逆向思维问题
(3)树结构遍历
(4)汉诺塔
(5)斐波那契数列
(6)深度优先搜索 DFS

4.递归示例

(1)汉诺塔问题

void HanNuoTa(int n, char src, char tmp, char dst)
{
    if(n == 1)
    {
        printf("%c->%c\n", src, dst);
    }
    else
    {
        HanNuoTa(n-1, src, dst, tmp);
        printf("%c->%c\n", src, dst);
        HanNuoTa(n-1, tmp, src, dst);
    }
}

(2)递归求 Fibonacci 数

int fib(int n)
{
    if(n == 1 || n == 2)
    {
       return 1;
    }
    return fib(n-1) + fib(n-2);
}

二、带参宏 vs 函数

1. 带参宏的特点

特点说明
无参数类型检查纯文本替换
无真正的返回值只是替换,不计算
没有参数传递开销因为不调用函数
代码块会展开体积变大
速度快无函数调用开销
适合简单逻辑复杂逻辑不适用

备注:带参宏必须注意括号!!!

#define ADD(a,b)   ((a)*(b))   //带括号
#define ADD(a,b)   a*b         //不带括号

例如:ADD(3,4+5)
带括号 → ((3)*(4+5)) 正确
不带括号 → 3*4+5 → 错

2. 函数(真实函数)的特点

特点说明
有类型检查安全
有返回值类型受类型限制
需要栈帧有调用开销
体积小不会展开
适合复杂逻辑多行代码

3.对比总结

项目带参宏函数
类型检查
返回值
参数传递直接替换需要传参
执行效率略低
可读性
代码大小增大(展开)小(共用)
适合简单功能复杂逻辑

三、预处理指令(Preprocessing)

GCC 编译过程
1.预处理(处理 # 相关内容)
2.编译(C → 汇编)
3.汇编(汇编 → .obj目标文件)
4.链接(生成可执行文件)
备注:所有以 # 开头的都是预处理指令。

四、常用预处理指令

1. 宏定义(与带参宏)

#define PI 3.14
#define ADD(a,b)   ((a)+(b))

规则:(1)不加分号 ;
(2)建议宏名用大写
(3)能带括号的尽量都带上

2. 头文件包含

#include <stdio.h>   // 直接到系统目录下查找,系统目录:/usr/include
#include "my.h"      // 先在当前目录查找,没找到再到系统目录查找

找不到头文件 →

fatal error: file.h: No such file or directory

3. 条件编译(重点)

(1)基本形式

#if 表达式
  代码1
#endif

(2)带 else

#if 表达式
  代码1
#else
  代码2
#endif

(3)带 elif

#if 表达式1
    代码1
#elif 表达式2
    代码2
#else
    代码3
#endif

4. 判断宏是否定义

(1)已经定义?

#ifdef DEBUG
    printf("debug on\n");
#endif

(2)没有定义?

#ifndef DEBUG
#define DEBUG
#endif

五、头文件的内容

.h 文件中一般存放:

1. 宏定义

#define MAX 100

2.typedef 别名

typedef unsigned int size_t;

3.函数声明

int add(int a, int b);

4.全局变量的 extern 声明

extern int result;

六、避免头文件被重复包含(防止重复定义)

标准写法

#ifndef _FUNC_H_
#define _FUNC_H_

extern int result;
extern int add(int a, int b);
extern int sub(int a, int b);

#endif  // _FUNC_H_

作用:让头文件只被编译一次,避免 redefinition 错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值