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

深⼊理解指针(7)

1.函数指针变量的创建

在x86环境下:

我们发现:以函数是有地址的,函数名就是函数的地址,当然也可以通过& 函数名 的⽅式获得函数的地址。

如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指针⾮常类似。如下:

函数指针类型解析: 

 

再加上一组:

发现pf的前面可以不带*

2.两段有趣的代码

 
    (*(void (*)())0)();
    //解释一下
    // void (*)()—— 是函数指针类型
    //(void (*)()) —— 括弧里面放类型就是强制转换
    //(void (*)())0 —— 将0强制转换为 void (*)() 的函数指针类型
    //这就意味着我们假设 0 地址处放着无参,返回类型是 void 的函数
    //最终是调用 0 地址处放的这个函数

 void (* signal( int, void(*)(int) ) )(int);
// signal —— 函数名
// int —— 参数1
// void(*)(int) —— 参数2
// signal( int, void(*)(int) ) —— 其中少函数值的返回类型
// 而剩下的void ( )(int); —— 这就是返回类型
// 所以这段代码本质是一个函数声明
// 想表达的意思是:
// void (*)(int)signal( int, void(*)(int) )
// 注意像上一行这样写是会报错的
// 只是想要表达这个意思而已

3.typedef关键字

typedef 是⽤来类型重命名的,可以将复杂的类型,简单化。⽐如,你觉得unsigned int 写起来不⽅便,如果能写成 uint 就⽅便多了,那么我们可以使⽤:

如果是指针类型,能否重命名呢?其实也是可以的,⽐如,将int* 重命名为 ptr_t ,这样写:

但是对于数组指针和函数指针稍微有点区别:

⽐如我们有数组指针类型 int(*)[5] ,需要重命名为 parr_t ,那可以这样写:

注意:

// 新的类型名必须在 * 的右边

函数指针类型的重命名也是⼀样的,⽐如,将 void(*)(int)  类型重命名为  pf_t  ,就可以这样写:

那么要简化上述的代码2,可以这样写:

typedef void(*pfun_t)(int);

pfun_t signal(int, pfun_t);

本篇文章中所用到的代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//int Add(int x, int y)
//{
//	return x + y;
//}
//int main()
//{
//	printf("%p\n", Add);
//	printf("%p\n", &Add);
//	return 0;
//}//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int main()
//{
//	//回忆一下数组指针
//	//int arr[10] = { 0 };
//	//int (*pa)[10] = &arr;
//	//函数与数组类似
//	int (* pf)(int, int) = &Add;
//	//(int, int) 是因为(int x, int y)
//	// int (* pf)是因为int Add
//	//pf是专门用来存放函数地址的,pf 就是函数指针变量
//	return 0;
//}//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int main()
//{
//	int(*pf)(int, int) = Add;
//
//	int c = Add(2, 3);
//	//函数名调用
//	printf("%d\n", c);
//
//	int d = (*pf)(3, 4);
//	//函数指针变量调用
//	printf("%d\n", d);
//
//	int e = (pf)(4, 5);
//	//函数指针变量调用
//	printf("%d\n", e);
//
//	return 0;
//}看看有趣的代码
//int main()
//{
//	(*(void (*)())0)();
//	//解释一下
//	// void (*)()—— 是函数指针类型
//	//(void (*)()) —— 括弧里面放类型就是强制转换
//	//(void (*)())0 —— 将0强制转换为 void (*)() 的函数指针类型
//	//这就意味着我们假设 0 地址处放着无参,返回类型是 void 的函数
//	//最终是调用 0 地址处放的这个函数
//	return 0;
//}//void (* signal( int, void(*)(int) ) )(int);signal —— 函数名int —— 参数1void(*)(int) —— 参数2signal( int, void(*)(int) ) —— 其中少函数值的返回类型而剩下的void ( )(int); —— 这就是返回类型所以这段代码本质是一个函数声明想表达的意思是:void (*)(int)signal( int, void(*)(int) )注意像上一行这样写是会报错的只是想要表达这个意思而已
//
//int main()
//{
//
//	return 0;
//}

http://www.xdnf.cn/news/224857.html

相关文章:

  • Python网络爬虫核心技术拆解:架构设计与工程化实战深度解析
  • 【数据通信完全指南】从物理层到协议栈的深度解析
  • 鸿蒙移动应用开发--ArkTS语法进阶实验
  • 【MongoDB篇】MongoDB的索引操作!
  • Spring Boot 中集成 Kafka 并实现延迟消息队列
  • 腾讯云服务器性能提升全栈指南(2025版)
  • C# 类成员的访问:内部与外部
  • 练习001
  • Java进阶--设计模式
  • 汽车OTA在线升级法规分析
  • 搭建基于 ChatGPT 的问答系统
  • Linux Quota 显示空间占用远大于实际数据的问题排查记录
  • Java写数据结构:队列
  • 基于大模型的膀胱肿瘤全周期诊疗方案研究报告
  • 【KWDB 创作者计划】_KWDB能帮我的项目解决什么问题
  • Golang - 实现文件管理服务器
  • scGPT方法解读
  • 突发-2小时前DeepSeek发布了新模型-不是R2
  • 中小企业如何借助智能海关系统降低跨境运输成本?
  • day006-实战练习题-参考答案
  • 基于 IAR Embedded Workbench 的自研 MCU 芯片软件函数与变量内存布局优化精控方法
  • LeetCode 2905 找出满足差值条件的下标II 题解
  • AI驱动的决策智能系统(AIDP)和自然语言交互式分析
  • ArcGIS+GPT:多领域地理分析与决策新方案
  • 第十一节:Shell脚本编程
  • 软件架构选型之“如何选”
  • Walrus 与 Pudgy Penguins 达成合作,为 Web3 头部 IP 引入去中心化存储
  • 米壳AI:跨境电商图片翻译的“隐形革命”:当AI技术遇上全球化生意
  • Azure Monitor 实战指南:全方位监控应用与基础设施
  • 零基础学指针2