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. JS ellipse 转 PathData

    绘制Path function ellipse2path(cx, cy, rx, ry, degree) { //cx cy:圆心 //rx ry:x y 轴长 //degree:度数,顺时针方向为正 ...

  2. cmd - windows操作系统命令提示符常用命令

    mklink /j C:\Users\lin_0421\Desktop\note D:\note

  3. Redis高可用部署:3台服务器打造哨兵集群

    1.Redis集群介绍 Redis 集群(Redis Cluster)是Redis提供的一种分布式部署方式,旨在提供高可用性.如果某个主节点发生故障,集群能够自动进行故障转移,将副本提升为主节点,从而 ...

  4. 【论文随笔】会话推荐系统综述(A Survey on Conversational Recommender Systems)

    前言 今天读的论文为一篇于2021年5月发表在<ACM计算机调查>(ACM Computing Surveys)的论文,文章提供了对话式推荐系统(CRS)的全面综述,探讨了CRS的定义.概 ...

  5. CTF-CRYPTO-ECC(2)

    CTF-CRYPTO-ECC(2) 椭圆加密 4.BSGS(小步大步法) [HITCTF 2021 ] task.py #Elliptic Curve: y^2 = x^3 + 7 mod N whi ...

  6. Web前端入门第1问:英语是否很重要?有哪些前置条件?

    HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 在入门之前,是否有这样的疑问: 程序员的英语是否很牛?毕竟程序员的代码像天书一样,比如这样: 答案是否定的. 英 ...

  7. Mac下打开进入/usr/local等隐藏目录

    教程 Mac下/usr/local目录默认是对于Finder是隐藏,如果需要到/usr/local下去,打开Finder,然后使用command+shift+G,在弹出的目录中填写/usr/local ...

  8. Golang 入门 : 转换

    Go中数学运算和比较运算要求包含的值具有相同的类型.如果不是的话,则在尝试运行代码时会报错. 为变量分配新值也是如此.如果所赋值的类型与变量的声明类型不匹配,也会报错. 解决方法是使用转换,它允许你将 ...

  9. 【高德地图】离线地图jsapi2.0 插件引用

    当引用一个插件,但是这个插件没有时会报错: Uncaught TypeError: AMap.ControlBar is not a constructor 这里引用了罗盘这个插件 这时候需要翻看高德 ...

  10. 实现领域驱动设计 - 使用ABP框架 - 领域逻辑 & 应用逻辑

    领域逻辑 & 应用逻辑 如前所述,领域驱动设计中的业务逻辑分为两部分(层):领域逻辑和应用逻辑: 领域逻辑由系统的核心领域规则组成,应用逻辑实现应用特定的用例 虽然定义很明确,但实现起来可能并 ...