当前位置:首页 > 技术 > 正文内容

C语言核心特性:递归机制与指针操作详解

访客 技术 2026年5月21日 3

递归函数的实现原理

递归的本质是函数在执行过程中对自身发起调用,形成层层嵌套的调用链。这与堆栈结构天然契合——每次调用都会将当前状态压入栈中,待深层调用返回后再逐层恢复。

递归可靠运行的两个必要条件:

  1. 存在明确的终止条件,防止无限循环
  2. 每次递归调用都向终止条件靠近

以下通过斐波那契数列展示递归的经典应用:

#include <stdio.h>

// 计算斐波那契数列第 n 项
int fib(int idx)
{
    if (idx <= 2) {
        return 1;  // 终止条件
    }
    return fib(idx - 1) + fib(idx - 2);  // 递归向终止条件收敛
}

int main()
{
    for (int i = 1; i <= 8; i++) {
        printf("fib(%d) = %d\n", i, fib(i));
    }
    return 0;
}

标准库函数精选

字符串处理

引入 <string.h> 头文件,常用操作如下:

函数原型功能说明
size_t strnlen(const char *s, size_t maxlen)获取字符串有效长度(安全版本)
char *strncpy(char *dest, const char *src, size_t n)带长度限制的字符串复制
char *strncat(char *dest, const char *src, size_t n)带长度限制的字符串拼接

格式化字符串操作(<stdio.h>):

char buf[128];
int val = 42;
snprintf(buf, sizeof(buf), "数值为: %d", val);  // 安全写入字符串

int parsed;
const char *src = "数值为: 42";
sscanf(src, "数值为: %d", &parsed);  // 从字符串解析数据

时间日期操作

<time.h> 提供的时间工具:

#include <time.h>
#include <stdio.h>

int main()
{
    time_t now, past;
    
    now = time(NULL);           // 获取当前时间戳
    past = now - 86400;         // 一天前的秒数
    
    printf("当前: %s", ctime(&now));
    printf("间隔: %.f 秒\n", difftime(now, past));
    
    return 0;
}

数学运算函数

<math.h> 中的数值计算工具:

#include <math.h>

double x = 2.5, y = 3.0;
double result;

result = sqrt(x);      // 算术平方根
result = cbrt(x);      // 立方根
result = pow(x, y);    // x 的 y 次幂
result = fabs(-x);     // 绝对值
result = ceil(x);      // 向正无穷取整 → 3.0
result = floor(x);     // 向负无穷取整 → 2.0
result = round(x);     // 四舍五入 → 3.0
result = trunc(x);     // 截断小数 → 2.0

指针深度解析

指针的本质与声明

指针变量存储的是内存单元的编号,其类型决定了对地址的解释方式:

int    *ip;     // 指向整型的指针
double *dp;     // 指向双精度浮点的指针
void   *vp;     // 泛型指针,需强制转换后使用

关键运算符:

  • &:取址运算符,获取变量的内存地址
  • *:间接访问运算符,通过地址读取或修改目标数据

指针的算术运算

指针运算以数据类型宽度为基本单位:

int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr;      // 指向首元素

ptr += 2;            // 偏移至第3个元素(地址增加 2*sizeof(int))
printf("%d\n", *ptr);  // 输出 30

int *qtr = &arr[4];
ptrdiff_t dist = qtr - ptr;  // 同类型指针相减,得元素间隔数

指针与数组的关系

数组标识符在表达式中通常退化为指向首元素的指针,但二者存在关键差异:

特性数组名指针变量
可修改性不可赋值,地址固定可重新指向其他地址
自增/自减不支持支持
sizeof 结果整个数组的字节数指针本身的字节数(4/8)
访问元素arr[i]*(arr+i)ptr[i]*(ptr+i)

遍历数组的指针写法:

int nums[] = {5, 9, 13, 17, 21};
int *end = nums + 5;     // 末尾元素的下一个位置

for (int *cursor = nums; cursor < end; cursor++) {
    printf("%d ", *cursor);   // 通过解引用访问当前元素
}

多级指针与常量指针

int value = 100;
int *p1 = &value;       // 一级指针
int **p2 = &p1;         // 二级指针,指向指针的指针

const int *pc = &value;     // 指向常量的指针:不可通过 pc 修改 value
int *const cp = &value;     // 常量指针:cp 不可指向其他地址
const int *const cpc = &value;  // 双重限制

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。