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

void指针为何能幻化有数据类型?

一.测试环境

   qt5.12

二.void指针

1.void指针

void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据。和用int表示指针异曲同工,只是更明确是“指针”。

因此void *只能表示一个地址,不能用来&取值,也不能++和--移动指针,因此不知道多少字节是一个数据单位。

示例:

    int nums[] = {3,5,6,7,9};

    void* ptr1 = nums;

    //int i = *ptr1; // 对于void指针没法直接取值

    int* ptr2 = (int*)nums;

    qDebug()<<ptr1<<ptr2;

    int i = *ptr2;

qDebug()<<i;

从输出结果上,无论是无类型的void指针还是int类型指针,指向的地址都是一样的:

说明:void *就是一个不能动的“地址”,在进行&、移动指针之前必须转型为类型指针。

2.void指针的用途

(1)memset 函数是 C 语言标准库中的一个函数,常用于将一段内存区域设置为指定的值。

#include <string.h>

函数原型:void *memset(void *s, int c, size_t n);

代码示例:

#include <stdio.h>

#include <string.h>

int main() {

    int str[10];

    // 使用 memset 将 str 数组全部置位0

    memset(str, 0, sizeof(str));

    qDebug()<<"len=" << sizeof(str);

    for (int i = 0; i < 10; i++) {

        qDebug()<<str[i];

    }

    return 0;

}

输出结果:

说明:

void *的用途:在只知道内存,但是不知道是什么类型的时候。

三.函数指针

  1.指向函数的指针

我们可以在C中定义一个函数指针:

typedef void (*intFunc)(int i);

这里我们定义了一个无返回值的,只有一个int类型参数的函数指针intFunc。

我们可以在main函数中使用这个函数指针来指向一个具体的函数(这个具体的函数定义需要和函数指针的定义一致):

代码示例:

typedef void (*intFunc)(int i);

void test1(int age){

    qDebug()<<"test1:%d\n",age);

}

int main(void){

    

    // 声明一个intFunc类型的函数指针

    intFunc f1 = test1;

    // 执行f1函数指针所指向的代码区

    f1(8);

    return 0;

}

最终运行结果为:8,执行函数指针f1即执行了其所指向的具体的函数。

2.函数指针的基本使用

这里我们通过一个小案例来对函数指针做一个基本的使用介绍。相信大部分的C#或Java程序员都很熟悉foreach,那么我们就来模拟foreach对int数组中的值进行不同的处理。

具体体现为for循环的代码是复用的,但是怎么处理这些数据不确定,因此把处理数据的逻辑由函数指针指定。

void foreachNums(int *nums,int len,intFunc func)

{

    int i;

    for(i=0;i<len;i++)

    {

        int num = nums[i];

        func(num);

    }

}

void printNum(int num)

{

    qDebug()<<num;

}

在foreachNums函数中,我们定义了一个intFunc函数指针,printNum函数是满足intFunc定义的一个具体的函数。

下面我们在main函数中将printNum函数作为函数指针传递给foreachNums函数。

    int nums[] = { 1,5,666,23423,223 };

    foreachNums(nums,sizeof(nums)/sizeof(int),printNum);

最终运行的结果如下图所示:

通过函数指针,我们可以屏蔽各种具体处理方法的不同,也就是将不确定的因素都依赖于抽象,这也是面向抽象或面向接口编程的精髓。

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

相关文章:

  • Linux下的I/O复用技术之epoll
  • Linux:进程间通信->命名管道
  • 【WSL】wsl2出现Exec format error的解决办法
  • 矫平机终极指南:特殊材料处理、工艺链协同与全球供应链管理
  • Java 线程的六种状态与完整生命周期详解
  • YOLOv8改进新路径:Damo-YOLO与Dyhead融合的创新检测策略
  • C语言学习之调试
  • 小白自学python第三天
  • 当高级辅助驾驶遇上“安全驾校”:NVIDIA如何用技术给无人驾驶赋能?
  • Python类和对象四(十三)
  • 2025雅思口语工具Top10:AI软件真实测评
  • 在springboot项目中,如何进行excel表格的导入导出功能?
  • JavaScript基础-算数运算符
  • (四) 实战Trae 编译调试C++项目(以minidocx为例)
  • Winform(2.多线程)
  • C19-while循环及for循环等价引入
  • CANFD技术在实时运动控制系统中的应用:协议解析、性能测试与未来发展趋势
  • (23)VTK C++开发示例 --- 读取所有的PolyData类型示例
  • 网络管理知识点
  • Java----内部类 以及 调用关系
  • Pygame终极项目:从零开发一个完整2D游戏
  • C++之map
  • ngrok 内网穿透技术系统性文档
  • 初始网络流(最小割)
  • 【C语言练习】005. 编写表达式并确定其值
  • leetcode刷题日记——环形链表
  • 新增Webhook通知功能,文档目录树展示性能优化,zyplayer-doc 2.5.1 发布啦!
  • Linux基础篇、第4章_03系统磁盘高级管理LVM 逻辑卷管理器
  • 【头脑风暴】加权平均
  • 模型 递弱代偿