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. flutter - [03] 运算符&条件表达式

    题记部分 一.算术运算符 var a=13; var b=5; 运算符 说明 示例 结果输出 + 加 print(a+b); 18 - 减 print(a-b); 8 * 乘 print(a*b); ...

  2. FUSE,从内核到用户态文件系统的设计之路

    FUSE(Filesystem in Userspace)是一个允许用户在用户态创建自定义文件系统的接口,诞生于 2001 年.FUSE 的出现大大降低了文件系统开发的门槛,使得开发者能够在不修改内核 ...

  3. 2024.11.19随笔&联考总结

    联考 看到 T1 就知道一定是简单计数题然后发现 \(O(n)\) 可以过于是就大概写了写式子就开写.写的过程中犯了一些低级错误,代码重构了一次才过.耽误的时间比较久.然后开 T2,一眼有一个 \(O ...

  4. Jsoncpp的安装与使用方式

    JsonCpp 是一个C++库,用于解析和生成JSON数据.它支持解析JSON文件或字符串到C++对象,以及将C++对象序列化回JSON格式. 安装Jsoncpp 我们可以输入以下命令安装jsoncp ...

  5. 【MIPS】经典指令块集锦

    Directives声明变量值存储 容易将数据段地址和地址上的内容搞混 .data fibs: .space 48 # allocate 12 * 4 = 48 Byte memory, store ...

  6. go mod 安装bee 报错

    报错信息 go: github.com/beego/bee imports github.com/beego/bee/cmd imports github.com/beego/bee/cmd/comm ...

  7. Camel多智能体框架初探

    Camel介绍 CAMEL 是一个开源社区,致力于探索代理的扩展规律.我们相信,在大规模研究这些代理可以提供对其行为.能力和潜在风险的宝贵见解.为了促进该领域的研究,我们实现了并支持各种类型的代理.任 ...

  8. PLSQL定时任务创建 Oracle数据库dbms_job

    创建一个job job创建 begin sys.dbms_job.submit(job => 1, --代表的是号码,第几个定时任务 what => 'sys_mailing_list_j ...

  9. linux命令:lsof命令

    lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以如传输控制协议 ...

  10. Linux® 容器

    是与系统其他部分隔离开的一系列进程.运行这些进程所需的所有文件都由另一个镜像提供,这意味着从开发到测试再到生产的整个过程中,Linux 容器都具有可移植性和一致性.因而,相对于依赖重复传统测试环境的开 ...