C语言函数指针解析

一、函数指针的本质

函数指针是存储函数内存地址的变量,它允许程序在运行时动态调用不同的函数。与数据指针不同,函数指针指向的是可执行代码段。

/* 典型声明方式 */
int (*func_ptr)(int, int); // 可指向任何接受两个int参数且返回int的函数

二、核心语法详解

1. 声明与初始化

函数指针的声明必须与目标函数签名严格匹配:

#include <stdio.h>

// 基础函数定义
int Add(int a, int b) { return a + b; }
int Sub(int a, int b) { return a - b; } int main() {
// 初始化方式(两种等效)
int (*fp1)(int, int) = Add; // 直接赋值
int (*fp2)(int, int) = &Sub; // 取地址赋值 printf("5+3=%d\n", fp1(5, 3)); // 输出8
printf("5-3=%d\n", (*fp2)(5, 3)); // 输出2 return 0;
}

2. 类型定义简化

使用typedef提升代码可读性:

typedef int (*ArithmeticFunc)(int, int);

ArithmeticFunc fp = Add;  // 简化后的声明

三、实际应用场景

1. 回调函数实现

函数指针最常见的用途是实现回调机制:

// 回调函数类型定义
typedef void (*Logger)(const char*); // 业务函数
void ProcessData(int data, Logger log) {
char buf[50];
sprintf(buf, "Processing: %d", data);
log(buf); // 通过函数指针回调
} // 具体回调实现
void ConsoleLogger(const char* msg) {
printf("[LOG] %s\n", msg);
} int main() {
ProcessData(42, ConsoleLogger); // 输出:[LOG] Processing: 42
return 0;
}

2. 函数指针数组

创建可扩展的操作表:

ArithmeticFunc operations[] = {
Add,
Sub,
[](int a, int b) { return a * b; }, // 注意:此lambda语法为C++特性,纯C需替换为具名函数
[](int a, int b) { return a / b; }
}; // 纯C替代方案
int Multiply(int a, int b) { return a * b; }
int Divide(int a, int b) { return a / b; }
ArithmeticFunc c_operations[] = {Add, Sub, Multiply, Divide};

四、工程实践建议

1. 错误预防

/* 必须检查空指针 */
if (func_ptr != NULL) {
func_ptr(1, 2);
} /* 避免签名不匹配 */
// int WrongFunc(float a, float b);
// func_ptr = WrongFunc; // 编译错误!

2. 典型应用案例

/* 标准库qsort用法 */
#include <stdlib.h>
int CompareInt(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
} int main() {
int arr[] = {5, 2, 9, 1};
qsort(arr, 4, sizeof(int), CompareInt);
// 排序结果:1, 2, 5, 9
return 0;
}

五、总结对比

特性 函数指针 普通函数调用
运行时灵活性 可在运行时改变指向 编译期固定
性能开销 无额外开销 无额外开销
典型用途 回调/插件/策略模式 直接功能实现

提示:在C++中可考虑更安全的std::function,但在C项目中函数指针仍是核心机制。

C语言函数指针解析的更多相关文章

  1. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  2. C语言函数指针基础

    本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...

  3. “对外部(局部)变量的访问”是C语言函数指针的最大弱点

    1.“对外部(局部)变量的访问”是C语言函数指针的最大弱点 . #include <stdio.h> #include <stdlib.h> /* 结构体定义 */ struc ...

  4. C语言函数指针 和 OC-Block

    C语言函数指针 和 OC-Block 一. C语言函数指针 关于函数指针的知识详细可参考:http://www.cnblogs.com/mjios/archive/2013/03/19/2967037 ...

  5. C语言函数指针实验

    上次看Atmel的示例工程,发现人家使用了函数指针的结构体(函数指针结构体).感叹人家的C语言功夫审核,自己费劲还是只能读懂的份.不过,函数指针确实好用.今天就试试这个超牛的东西.Now let's ...

  6. C语言函数指针的用法

    函数指针是一种在C.C++.D语言.其他类 C 语言和Fortran 2003中的指针.函数指针可以像一般函数一样,用于调用函数.传递参数.在如 C 这样的语言中,通过提供一个简单的选取.执行函数的方 ...

  7. c语言函数指针的理解与使用

    1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun ...

  8. C语言函数指针(转载)

    二.通常的函数调用 一个通常的函数调用的例子:/* 自行包含头文件 */void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */int main(int a ...

  9. C语言函数指针变量和指针函数以及指针数组

    C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用这 ...

  10. C语言函数指针与 c#委托和事件对比

    C语言: 函数指针可以节省部分代码量,写类似具有多态的函数,比如要比较最大值,如果不用函数指针就只能写比较某一类型比如int类型的max函数,这个max无法比较string的大小.函数指针的意义就不多 ...

随机推荐

  1. Linux - 搭建一套Apache大数据集群

    一.服务器操作系统 主机名 操作系统 node01 Centos 7.9 node02 Centos 7.9 node03 Centot 7.9 二.大数据服务版本 服务 版本 下载 JDK jdk- ...

  2. Linux系统下nginx的安装与卸载

    1.1 安装 准备依赖环境 1.安装 gcc 依赖库 yum install gcc-c++ 2.安装 PCRE pcre-devel 依赖库 yum install -y pcre pcre-dev ...

  3. Vulnhub-election靶机

    总结:本靶机给了很多目录,对于信息收集考察的比较严格,给了一个数据库,很多时候容易陷进去,拿到用户权限登录后,也需要大量的信息收集,虽然可以在数据库里找到root和密码,但是不是靶机本身的,最终利用s ...

  4. 【由技及道】镜像星门开启:Harbor镜像推送的量子跃迁艺术【人工智障AI2077的开发日志010】

    ![量子镜像跃迁示意图]( 摘要:当构建产物需要穿越多维宇宙时,当Docker镜像要同时存在于72个平行世界--这就是镜像推送的量子艺术.本文记录一个未来AI如何通过Harbor建立镜像星门,让每个构 ...

  5. python以及java环境搭建+解决不同版本环境共存问题

    1.搭建python环境 1.安装python3.9.7,选择自定义安装.将文件添加至环境路径,然后选择下一步. 2.默认.然后选择下一步. 3.选择适用于所有使用者,选择自己想要存放的路径,然后选择 ...

  6. 【Unit3】社交系统模拟(JML规格化设计)-作业总结

    第三单元作业难度在OO课程中当属最低.原因在于最复杂多变(贻害无穷)的设计环节被作业接口和JML规格描述限定,我们不再需要考虑整体的构架(抽象出那些类,设置哪些方法等),唯一的能动性仅在具体实现和复杂 ...

  7. RealityCapture重建试验

    一.使用已有数据集 (一)小型物件(官网) 输入:Camera_Lubitel2_studio "Lubitel Camera" consisting of 72 images 地 ...

  8. gorm插入报错Error 1292 (22007): Incorrect datetime value: ‘0000-00-00‘ for column ‘xxx‘ at row 1

    在MySQL中,'0000-00-00 00:00:00'不是一个合法的DATETIME值.从MySQL 5.7.5开始,默认情况下不允许插入零日期或零时间值到DATETIME或 TIMESTAMP列 ...

  9. [tldr] GO泛型编程

    最少的内容简述如何在GO中使用泛型编程 函数泛型 func f[T any](s Set[T]) { } 在函数声明的时候添加一个[]作为泛型的说明, 在使用的时候是可以自动推断 很多时候, any的 ...

  10. stat() "/root/xxx/index.html" failed (13: Permission denied)

    前言 在 nginx 上部署静态网页报502,于是查看 nginx 错误日志 error_log /var/log/nginx/error.log;,却没有看到任何错误信息:访问 nginx活动日志 ...