当前位置: 首页 > article >正文

[学习]C语言指针函数与函数指针详解(代码示例)

C语言指针函数与函数指针详解

文章目录

  • C语言指针函数与函数指针详解
    • 一、引言
    • 二、指针函数(函数返回指针)
      • 定义与语法
      • 典型应用场景
      • 注意事项
    • 三、函数指针(指向函数的指针)
      • 定义与声明
      • 初始化与调用
        • 赋值方式
        • 调用语法
      • 高级应用
        • 回调函数实现
        • 函数指针数组(跳转表)
    • 四、对比与关联分析
      • 本质差异
      • 组合使用案例
    • 五、常见问题与陷阱
      • 指针函数风险
      • 函数指针陷阱
    • 六、实战案例
      • 案例1:通用排序函数
      • 案例2:状态机实现
    • 七、总结
      • 关键知识点回顾
      • 性能与灵活性权衡建议


一、引言

指针是C语言中最核心也最强大的特性之一,它直接操作内存地址的特性赋予了程序员极大的灵活性和控制力。通过指针,我们可以高效地处理数组、字符串和动态内存分配,实现复杂的数据结构如链表和树。据统计,超过80%的C语言项目都会涉及到指针操作,其在系统编程和嵌入式开发中尤为重要。

指针函数和函数指针是两个容易混淆但功能迥异的重要概念:

  1. 指针函数(pointer function)是指返回值为指针类型的函数,例如:
char *get_string(void);  // 返回字符指针的函数

这类函数常用于返回字符串或动态分配的内存,在文件操作和内存管理中应用广泛。

  1. 函数指针(function pointer)则是指向函数的指针变量,例如:
int (*pFunc)(int, int);  // 指向接收两个int参数并返回int的函数

函数指针在实现回调机制、策略模式和事件处理等场景中发挥着关键作用,比如:

  • GUI框架中的事件回调
  • 排序算法中的比较函数
  • 插件系统的接口调用

理解并掌握这两者的区别和使用场景,是提升C语言编程能力的重要一环。本文将通过具体实例详细分析它们的特点和应用方式。


二、指针函数(函数返回指针)

定义与语法

指针函数是指返回值为指针类型的函数,其声明语法为:

返回类型* 函数名(参数列表);

例如:

int* func(int a, int b);  // 返回整型指针的函数

在C语言中,指针函数的关键特征是通过*标识符来表明返回值是一个指针。这个指针可以指向任何数据类型,包括基本类型、数组、结构体等。

典型应用场景

  1. 动态内存分配
    标准库函数如malloccalloc都是典型的指针函数,它们返回动态分配的内存地址。例如:

    int* arr = (int*)malloc(10 * sizeof(int));
    
  2. 返回数组或字符串地址
    常用于返回字符串或数组的首地址。例如全局字符串处理:

    char* getGreeting() {static char greeting[] = "Hello World";return greeting;
    }
    
  3. 结构体指针传递
    高效传递大型结构体,避免复制开销。例如:

    struct Point* createPoint(int x, int y) {struct Point* p = malloc(sizeof(struct Point));p->x = x;p->y = y;return p;
    }
    

注意事项

  1. 栈内存陷阱
    绝对不要返回局部变量的地址,因为局部变量在函数返回后会被销毁。错误示例如下:

    char* faulty_func() {char str[] = "dangerous";  // 栈内存return str;  // 返回后将指向无效内存
    }
    
  2. 内存泄漏防范

    • 对于动态分配的内存,调用者必须负责释放
    • 推荐使用"分配-使用-释放"模式:
    int* nums = createArray(100);
    // 使用nums...
    free(nums);  // 必须释放
    
  3. 解决方案

    • 返回静态变量(但要注意线程安全问题)
    • 返回传入的指针参数
    • 使用动态内存分配并明确所有权
  4. 最佳实践示例

    char* safe_func() {char* str = malloc(100);strcpy(str, "safe string");return str;  // 调用者需要free
    }
    

这些扩展内容保持了原始信息的核心概念,同时增加了具体示例、语法说明和使用建议,使内容更加完整和实用。


三、函数指针(指向函数的指针)

定义与声明

int (*pFunc)(int, int);  // 函数指针声明:指向返回int且接受两个int参数的函数

函数指针的声明语法需要特别注意括号的位置。int (*pFunc)(int, int)表示pFunc是一个指针,指向一个接受两个int参数并返回int的函数。如果省略括号写成int *pFunc(int, int),就变成了一个返回int*的函数声明。

初始化与调用

赋值方式

函数指针可以通过两种等效的方式初始化:

int add(int a, int b) { return a + b; }
// 方式一:直接使用函数名(自动转换为函数指针)
pFunc = add;
// 方式二:显式取地址
pFunc = &add;
调用语法

调用函数指针也有两种等效语法:

// 方式一:直接调用(推荐)
printf("%d", pFunc(2, 3));  // 输出5
// 方式二:解引用调用
printf("%d", (*pFunc)(2, 3));

高级应用

回调函数实现

函数指针常用于实现回调机制,例如在排序算法中:

// 比较函数原型
typedef int (*CompareFunc)(const void*, const void*);void sort(int arr[], int size, CompareFunc cmp) {// 使用cmp函数比较元素
}int compareInt(const void* a, const void* b) {return (*(int*)a - *(int*)b);
}// 使用
int arr[] = {5, 2, 8, 1};
sort(arr, 4, compareInt);
函数指针数组(跳转表)

函数指针数组可用于实现命令模式或状态机:

void cmd1(void) { printf("Command 1\n"); }
void cmd2(void) { printf("Command 2\n"); }
void cmd3(void) { printf("Command 3\n"); }// 初始化函数指针数组
void (*commands[])(void) = {cmd1, cmd2, cmd3};// 根据输入调用不同命令
int input = 0;  // 假设0表示cmd1
commands[input]();  // 调用cmd1

这种模式在嵌入式系统中特别有用,可以快速实现命令调度。例如:

// 扩展为带参数的版本
typedef void (*CommandFunc)(int);
CommandFunc commands[] = {cmd1, cmd2, cmd3};void processCommand(int cmd, int arg) {if(cmd >= 0 && cmd < sizeof(commands)/sizeof(commands[0])) {commands[cmd](arg);}
}

四、对比与关联分析

本质差异

  • 指针函数:本质是函数,其返回值类型为指针类型。主要用于动态内存分配或返回数据结构的指针。例如:
int* create_array(int size) {return (int*)malloc(size * sizeof(int));
}
  • 函数指针:本质是指针变量,存储的是函数的入口地址。常用于实现回调机制或策略模式。例如:
int (*operation)(int, int);  // 声明函数指针
operation = add;  // 指向add函数

组合使用案例

  • 返回函数指针的函数:这种高阶用法可以实现运行时动态选择函数的功能,常用于命令模式或工厂模式。完整示例:
#include <stdio.h>int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }// 返回函数指针的函数
int (*get_operation(char op))(int, int) {switch(op) {case '+': return add;case '-': return sub;default: return NULL;}
}int main() {int (*operation)(int, int);operation = get_operation('+');printf("5+3=%d\n", operation(5, 3));operation = get_operation('-');printf("5-3=%d\n", operation(5, 3));return 0;
}

五、常见问题与陷阱

指针函数风险

  1. 野指针问题

    • 未初始化的指针或指向已释放内存的指针会导致不可预测的行为
    • 示例:int *p; *p = 10; 这种未初始化指针的使用可能引发段错误
    • 最佳实践:指针声明时立即初始化为NULL,使用前检查有效性
  2. 生命周期管理

    • 函数返回局部变量指针是常见错误,如:
      int* create_array() {int arr[10];return arr;  // 错误:arr是栈内存,函数结束即失效
      }
      
    • 解决方案:
      • 使用动态内存分配(malloc)并明确释放责任
      • 通过参数传入预分配内存
      • 使用静态变量(需注意线程安全问题)

函数指针陷阱

  1. 类型不匹配警告

    • 不同函数签名间的隐式转换可能导致未定义行为
    • 示例:将int (*)(int)赋值给void (*)(void)时编译器可能仅警告
    • 强制类型转换虽可消除警告,但不解决潜在的调用时参数传递问题
  2. void*与函数指针的转换限制

    • C标准明确禁止void*和函数指针间的直接转换
    • 常见错误场景:
      • 在泛型容器中试图用void*存储函数指针
      • 跨平台代码中通过void*传递函数指针
    • 替代方案:
      • 使用联合(union)类型包装
      • C11的_Generic选择机制
      • 保持严格的类型匹配,避免此类转换需求

六、实战案例

案例1:通用排序函数

  • 使用函数指针实现qsort式回调
    • 具体实现步骤:

      1. 定义一个通用的排序函数接口,接收数组指针、元素个数、单个元素大小及比较函数指针
        • 数组指针void *base可以指向任意类型的数据
        • size_t nmemb表示数组中的元素数量
        • size_t size指定每个元素占用的字节数
        • 比较函数指针用于定义元素间的比较规则
      2. 比较函数原型为:int (*compare)(const void *, const void *)
        • 该函数应返回:
          • 负值:第一个参数小于第二个参数
          • 零:两个参数相等
          • 正值:第一个参数大于第二个参数
        • 强制类型转换后执行具体比较逻辑
      3. 在排序过程中调用用户提供的比较函数来确定元素顺序
        • 使用memcpy或指针运算来交换元素
        • 排序算法可选择快速排序、归并排序等
        • 在比较元素时调用用户提供的compare函数
      4. 实际应用场景:可以对任意类型的数据进行排序,只需提供对应的比较逻辑
        • 对结构体数组排序:比较特定字段
        • 对字符串排序:使用strcmp作为比较函数
        • 对数值排序:直接比较数值大小
    • 示例代码片段:

      /* 通用排序函数 */
      void generic_sort(void *base, size_t nmemb, size_t size,int (*compare)(const void *, const void *)) {/* 使用冒泡排序算法示例 */for (size_t i = 0; i < nmemb-1; i++) {for (size_t j = 0; j < nmemb-i-1; j++) {void *a = (char *)base + j*size;void *b = (char *)base + (j+1)*size;if (compare(a, b) > 0) {/* 交换元素 */char temp[size];memcpy(temp, a, size);memcpy(a, b, size);memcpy(b, temp, size);}}}
      }/* 比较函数示例:整型比较 */
      int int_compare(const void *a, const void *b) {return (*(int *)a - *(int *)b);
      }/* 使用示例 */
      int main() {int arr[] = {4, 2, 8, 5, 1};generic_sort(arr, 5, sizeof(int), int_compare);return 0;
      }
      

案例2:状态机实现

  • 通过函数指针数组管理状态转换
    • 详细实现方案:

      1. 定义状态枚举和对应的处理函数类型

        • 首先使用enum定义所有可能的状态(如IDLE、PROCESSING、ERROR等)
        • 定义统一的状态处理函数类型,通常返回下一个状态值或bool表示是否终止
        typedef enum {STATE_IDLE,STATE_PROCESSING,STATE_ERROR,STATE_COUNT
        } State;typedef State (*StateHandler)(void* context);
        
      2. 创建状态处理函数数组,每个元素对应特定状态的处理逻辑

        • 按枚举顺序初始化函数指针数组
        • 每个处理函数实现特定状态的业务逻辑
        StateHandler state_handlers[STATE_COUNT] = {handle_idle_state,handle_processing_state,handle_error_state
        };
        
      3. 使用当前状态作为索引调用对应的处理函数

        • 在状态机主循环中通过current_state索引调用
        • 可添加状态有效性检查防止数组越界
        State next_state = state_handlers[current_state](context);
        
      4. 处理函数返回下一个状态或终止标志

        • 处理函数执行完成后必须返回有效的状态值
        • 可定义特殊状态值(如STATE_TERMINATE)表示状态机结束
    • 典型应用场景:

      • 协议解析(如TCP状态机)
        • 实现SYN_SENT、ESTABLISHED等TCP协议状态
        • 处理网络数据包时根据当前状态执行相应逻辑
      • 游戏角色AI状态管理
        • 定义IDLE、PATROL、ATTACK等状态
        • 根据游戏事件触发状态转换
      • 硬件设备控制流程
        • 实现INIT、READY、WORKING等设备状态
        • 通过状态机确保设备操作顺序正确
    • 扩展说明:

      1. 支持状态转换条件检查
        if(ready_to_process() && current_state == STATE_IDLE){next_state = STATE_PROCESSING;
        }
        
      2. 可添加状态进入/离开的回调函数
      3. 支持状态历史记录,便于调试

      完整示例代码:

       // 状态定义typedef enum {STATE_IDLE,STATE_PROCESSING,STATE_ERROR,STATE_COUNT} State;// 状态处理函数类型typedef State (*StateHandler)(void* context);// 各状态处理函数实现State handle_idle(void* ctx) {if(has_work()) return STATE_PROCESSING;return STATE_IDLE;}State handle_processing(void* ctx) {if(process_complete()) return STATE_IDLE;if(process_failed()) return STATE_ERROR;return STATE_PROCESSING;}// 状态处理函数表StateHandler state_table[STATE_COUNT] = {handle_idle,handle_processing,handle_error};// 状态机主循环void state_machine_run(void* context) {State current = STATE_IDLE;while(current < STATE_COUNT) {current = state_table[current](context);}}
      

七、总结

关键知识点回顾

  1. 性能优化

    • 计算效率:减少不必要的计算,合理选择算法的时间复杂度(如从 O(n²) 优化至 O(n log n))。
    • 资源管理:避免内存泄漏,合理使用缓存(如 Redis)以减少数据库查询次数。
    • 并发处理:采用多线程、异步 I/O(如 Python 的 asyncio)或分布式计算(如 Spark)提升吞吐量。
  2. 灵活性考量

    • 模块化设计:通过接口抽象(如 REST API 或 gRPC)降低模块间的耦合度,便于独立扩展。
    • 配置化:将业务规则(如定价策略或风控阈值)外置到配置文件或数据库,支持动态调整。
    • 插件机制:通过动态加载组件(如 Java 的 SPI 或 Python 的 importlib)实现功能热插拔。
  3. 典型应用场景

    • 高性能优先:高频交易系统、实时流数据处理(如 Flink 作业)需极致优化,通常牺牲部分灵活性。
    • 灵活扩展优先:电商促销系统、SaaS 多租户架构需快速适配业务变化,可能接受可控的性能损耗。

性能与灵活性权衡建议

决策因素倾向性能的选择倾向灵活性的选择
架构设计单体/紧密耦合(如 C++ 微服务)微服务/事件驱动(如 Kafka 消息总线)
数据存储嵌入式数据库(如 SQLite)分布式 NoSQL(如 MongoDB)
开发迭代速度长周期优化(如 GPU 加速算法)敏捷发布(如 Feature Toggle 开关)

平衡策略

  • 分层设计:核心链路(如支付引擎)保障性能,外围业务(如日志分析)采用可扩展架构。
  • 动态降级:在流量高峰时关闭非关键功能(如个性化推荐),通过熔断机制(如 Hystrix)保核心性能。
  • 性能预算:为灵活性组件设置性能阈值(如 API 响应时间 ≤200ms),超出时触发优化流程。

研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


相关文章:

[学习]C语言指针函数与函数指针详解(代码示例)

C语言指针函数与函数指针详解 文章目录 C语言指针函数与函数指针详解一、引言二、指针函数&#xff08;函数返回指针&#xff09;定义与语法典型应用场景注意事项 三、函数指针&#xff08;指向函数的指针&#xff09;定义与声明初始化与调用赋值方式调用语法 高级应用回调函数…...

夏季用电高峰如何防患于未“燃”?电力测温技术守护城市生命线

随着夏季来临用电负荷激增&#xff0c;电力系统面临严峻的高温考验&#xff0c;电力测温技术的重要性愈发凸显&#xff0c;电力安全是城市生命线工程的核心环节&#xff0c;电力测温已从"可选功能"升级为"必要的基础安全设施"。通过实时感知、智能分析和快…...

浙大版《Python 程序设计》题目集6-3,6-4,6-5,6-6列表或元组的数字元素求和及其变式(递归解法)

目录 6-3 输入格式: 输出格式: 输入样例: 输出样例: 6-4 输入格式: 输出格式: 输入样例: 输出样例: 6-5 输入格式: 输出格式: 输入样例: 输出样例: 6-6 输入格式: 输出格式: 输入样例: 输出样例: 6-3 第6章-3 列表或元组的数字元素求和 分数 20 全屏浏览 切换布局 作者 陈春晖 …...

Leetcode 3563. Lexicographically Smallest String After Adjacent Removals

Leetcode 3563. Lexicographically Smallest String After Adjacent Removals 1. 解题思路2. 代码实现 题目链接&#xff1a;3563. Lexicographically Smallest String After Adjacent Removals 1. 解题思路 这次的最后一题同样没有自力搞定&#xff0c;简直了…… 这道题还…...

【创造型模式】抽象工厂方法模式

文章目录 抽象工厂方法模式产品族与产品等级结构抽象工厂方法模式的角色和职责抽象工厂方法模式的实现抽象工厂方法模式的优缺点适用场景 抽象工厂方法模式 工厂方法模式引入了“工厂等级结构”&#xff0c;解决了简单工厂方法过分依赖单一工厂的问题。但是工厂方法模式存在的一…...

一台手机怎样实现多IP上网?方法有多种

在数字时代&#xff0c;多IP上网已成为许多手机用户的刚需。本文将详细介绍如何通过不同技术手段实现手机多IP上网&#xff0c;帮助读者根据实际需求选择适合的解决方案。 一、为什么一台手机要实现多IP上网 手机实现多IP上网的典型场景包括&#xff1a; ①防止同一IP操作多个…...

【FFmpeg+SDL】播放音频时,声音正常但是有杂音问题(已解决)

下面这个函数是SDL音频的回调函数(修改后的) void fill_audio(void *udata,Uint8 *stream,int len) {static int cc 0;cc;qDebug()<<QString::fromLocal8Bit("想要填充:%1字节").arg(len)<<cc;AudioOutput* is static_cast<AudioOutput*>(udat…...

Linux 527 重定向 2>1 rsync定时同步(未完)

rsync定时同步 配环境 关闭防火墙、selinux systemctl stop firewalld systemctl disable firewalld setenforce0 vim /etc/SELINUX/config SELINUXdisable515 设置主机名 systemctl set-hostname code systemctl set-hostname backup 配静态ip rsync 需要稳定的路由表和端…...

3DVR拍摄指南:从理论到实践

3DVR拍摄指南&#xff1a;从理论到实践 3D虚拟现实&#xff08;Virtual Reality,简称VR&#xff09;作为近年来迅速崛起的高新技术&#xff0c;通过电脑模拟产生一个三维空间的虚拟世界&#xff0c;为使用者提供视觉、听觉乃至触觉的全方位感官模拟&#xff0c;使用户仿佛身临…...

OSI模型中的网络协议

一、电子邮件协议&#xff1a;从SMTP到MIME的扩展 电子邮件系统的核心协议包括SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;、POP3&#xff08;Post Office Protocol&#xff09;和IMAP&#xff08;Internet Message Access Protocol&#xff09;&#xff0c;但…...

【C/C++】线程局部存储:原理与应用详解

文章目录 1 基础概念1.1 定义1.2 初始化规则1.3 全局TLS vs 局部静态TLS 2 内存布局2.1 实现机制2.2 典型内存结构2.3 性能特点 3 使用场景/用途3.1 场景3.2 用途 4 注意事项5 对比其他技术6 示例代码7 建议7.1 调试7.2 优化 8 学习资料9 总结 在 C 多线程编程中&#xff0c;线…...

分块查找详解

1、原理 分块查找&#xff08;Block Search&#xff09;是一种结合顺序查找与索引查找的算法&#xff0c;适用于数据分块存储且块内无序但块间有序的场景。它通过“分块-建立索引-逐层定位”提高查找效率。 分块查找的核心思想 数据分块 将数据集划分为若干块&#xff08;子…...

leetcode hot100刷题日记——21.不同路径

和20题一样的思路link 题解&#xff1a; class Solution { public:int dfs(int i,int j,vector<vector<int>>&memo){//超过了边界&#xff0c;return 0if(i<0||j<0){return 0;}//从&#xff08;0&#xff0c;0&#xff09;到&#xff08;0&#xff0c;0…...

Elasticsearch 如何实现跨数据中心的数据同步?

实战场景&#xff1a; 双数据中心容灾&#xff0c;要求RPO<5分钟&#xff0c;RTO<30分钟 ‌RPO&#xff08;Recovery Point Objective&#xff09;‌&#xff1a; RPO指的是灾难发生后&#xff0c;系统能够恢复到的数据更新点的时间。简单来说&#xff0c;它衡量的是数据…...

C语言学习笔记三 --- V

文章目录 程序入门设计 --- C 语言第二周 核心语法📝2.1 C 语言笔记 | 注释的使用(让代码会“说话”)💡 **注释的作用**🔍 **注释的两种写法**⚠️ **注释的注意事项**🔧 **注释的实用场景**📌 **本节总结**:📝 2.2 C 语言笔记 | 关键字(保留字)深度解析💡 …...

通过JS模板引擎实现动态模块组件(Vite+JS+Handlebars)

1. 引言 在上一篇文章《实现一个前端动态模块组件(Vite原生JS)》中&#xff0c;笔者通过原生的JavaScript实现了一个动态的模块组件。但是这个实现并不完善&#xff0c;最大的问题就是功能逻辑并没有完全分开。比如模块的HTML&#xff1a; <div class"category-secti…...

梯度消失和梯度爆炸的原因及解决办法

梯度消失和梯度爆炸的原因是什么 问题分析 梯度消失&#xff08;Vanishing Gradient&#xff09;和梯度爆炸&#xff08;Exploding Gradient&#xff09;本质上都是在深层神经网络中反向传播过程中&#xff0c;梯度在多层传播时逐渐缩小或放大的问题&#xff0c;导致模型难以…...

欧拉定理:若 gcd(a,n)=1,则 a^φ(n)≡1(mod n)。

【欧拉定理简介】 欧拉定理&#xff1a;若 gcd(a,n)1&#xff0c;则 a^φ(n)≡1(mod n)。 &#xff08;1&#xff09;例如&#xff0c;a3&#xff0c;n10&#xff0c;gcd(3,10)1&#xff0c;φ(10)4&#xff0c;则 a^φ(n)3^481&#xff0c;81 mod 101&#xff0c;欧拉定理成立…...

fvm install 下载超时 过慢 fvm常用命令、flutter常用命令

Git 配置问题 确保 Git 使用的是 HTTPS&#xff0c;而不是 SSH。如果你有 .gitconfig&#xff0c;确保没有配置奇怪的代理&#xff1a; git config --global --get http.proxy git config --global --get https.proxy如果有代理设置且不需要&#xff0c;取消代理&#xff1a;…...

Python正则表达式:30秒精通文本处理

一、概述 1. 含义 正则表达式是一种记录文本规则的代码工具&#xff0c;用于描述字符串的结构和模式。它广泛应用于字符串的匹配、查找、替换、提取等操作。 2. 特点 语法复杂&#xff1a;符号多、规则灵活&#xff0c;可读性较差。功能强大&#xff1a;可以精确控制字符串…...

Introduction to SQL

目录 SQL特点 ​编辑 Select-From-Where Statements Meaning of Single-Relation Query Operational Semantics * In SELECT clauses Complex Conditions in WHERE Clause PATTERNS NULL Values Three-Valued Logic Multirelation Queries Aggregations NULL’s Ig…...

计算机视觉---YOLOv3

YOLOv3讲解 一、YOLOv3 核心架构与创新 YOLOv3&#xff08;2018年发布&#xff09;在YOLOv2基础上进行了全面升级&#xff0c;通过多尺度预测、更强大的骨干网络和优化的分类损失函数&#xff0c;显著提升了检测精度&#xff0c;尤其是小目标检测能力&#xff0c;同时保持了实…...

#RabbitMQ# 消息队列进阶

目录 消息可靠性 一 生产者的可靠性 1 生产者的重连 2 生产者的确认 (1 Confirm* (2 Return 二 MQ的可靠性 1 数据持久化 2 Lazy Queue* 三 消费者的可靠性 1 消费者确认机制 2 消费失败处理 3 业务幂等性 四 延迟消息 消息可靠性 在消息队列中&#xff0c;可靠性…...

React从基础入门到高级实战:React 核心技术 - React Router:路由管理

React Router&#xff1a;路由管理 在现代 Web 应用开发中&#xff0c;路由管理 是构建多页面或单页应用&#xff08;SPA&#xff09;的核心技术之一。React Router 是 React 生态中最受欢迎的路由管理库&#xff0c;它为开发者提供了强大的工具来实现页面导航、动态路由和权限…...

【深度学习】损失“三位一体”——从 Fisher 的最大似然到 Shannon 的交叉熵再到 KL 散度,并走进 PET·P-Tuning微调·知识蒸馏的实战

一页速览&#xff1a; 1912 Fisher 用最大似然把「让数据出现概率最高」变成参数学习&#xff1b; 1948 Shannon 把交叉熵解释成「最短平均编码长度」&#xff1b; 1951 Kullback-Leibler 用相对熵量化「多余信息」。 三条历史线落到今天深度学习同一个损失——交叉熵。 也…...

5 分钟速通密码学!

让我们开始第一部分&#xff1a;密码学基础 (Cryptography Basics)。 第一部分&#xff1a;密码学基础 (Cryptography Basics) 1. 什么是密码学&#xff1f; 想象一下&#xff0c;在古代战争中&#xff0c;将军需要向远方的部队传递作战指令。如果直接派人送信&#xff0c;信…...

Linux——IP协议

1. 现实意义 • IP协议&#xff1a;提供一种能力&#xff0c;把数据报从主机A跨网络送到主机B • TCP/IP协议&#xff1a;核心功能&#xff0c;把数据100%可靠的从主机A跨网络送到主机B 注&#xff1a;TCP协议负责百分百可靠&#xff0c;通过三次握手、滑动窗口、拥塞控制、延…...

Lua 脚本在 Redis 中的运用-24 (使用 Lua 脚本实现原子计数器)

实践练习:使用 Lua 脚本实现原子计数器 实现原子计数器是许多应用程序中的常见需求,例如跟踪网站访问量、限制 API 请求或管理库存。虽然 Redis 提供了 INCR 命令用于递增整数,但在复杂场景或与其他操作结合时直接使用它可能并不足够。本课程探讨了如何在 Redis 中利用 Lua…...

Linux信号量(32)

文章目录 前言一、POSIX 信号量信号量的基础知识信号量的基本操作 二、基于环形队列实现生产者消费者模型环形队列单生产单消费模型多生产多消费模型 总结 前言 加油&#xff0c;加油&#xff01;&#xff01;&#xff01; 一、POSIX 信号量 信号量的基础知识 互斥、同步 不只…...

技术视界 | 打造“有脑有身”的机器人:ABC大脑架构深度解析(上)

ABC大脑架构&#xff1a;连接大模型与物理世界的具身智能新范式 在具身智能和类人机器人技术快速发展的背景下&#xff0c;如何高效整合“大模型的认知理解能力”与“对真实物理世界的精准控制”&#xff0c;成为当前智能体系统设计中最具挑战性也是最关键的问题之一。尽管大语…...