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

如何理解C++中的void*

1.什么是void*

首先void*中的void代表一个任意的数据类型,"星号"代表一个指针,所以其就是一个任意数据类型的指针。

其实就是一个未指定跳跃力的指针

那void*的跳跃力又什么时候指定?在需要使用的时候指定就可以了,好处:可以实现泛型编程,节省代码

对于指定数据类型的指针如int* ,double*等,他们的sizeof都是4个字节,因为都是一个指针,只是指针指向的数据类型不一致。

2.void*使用场景

      2.1:当函数传参是个指针时,不确定数据类型时或者支持多种数据类型传递时。

      2.2:函数返回值不需要考虑类型,只关心返回的大小。

     

 3.void*使用中的注意点:

  1.使用赋值运算符“=”时,void*只能作为左值不能作为右值。

void*作为一个未指定数据类型的指针,可以指向任何一个数据类型的指针,但是有数据类型的指针,不能指向一个void* 的指针。

int i = 5;
int* pi = &i;
void* pv = pi;
int* pi1 = pv;//编译错误,void*类型的指针不能初始化为指定类型的指针
 

 2.void*类型必须强转为指定类型的数据才能使用。

 void*在未指定类型的情况下,是不能直接使用的,只有在转换为显示类型后才能使用

void*一定要强转为具体指针类型后才能使用. 没有强转的void*是没有意义的。

 int i = 5;
    int* pi = &i;
    void* pv = pi;
     //cout << *pv << endl;//表达式必须是指向完整对象类型的指针
    int*  pip =  (int*)pv;
    cout << " *pip="<<*pip << endl;  // *pip=5

3. 使用(void*)0表示空指针。

  在C语言中空指针定义方式:

  在C语言中NULL代表(void*)0,

#define NULL ((void*)0)

在C++语言中:

在C++中NULL代表的是0,使用nullptr来表示(void*)0空指针,

所以在C++中推荐使用新标准的nullptr来初始化一个空指针。

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else 
        #define NULL ((void*)0)
    #endif
#endif
 

4.当void*作为函数的参数类型或者返回值类型时,说明该函数可以接收或者返回任意类型的指针。 

	/*void* pVoid 可以使用任意类型的实参指针类型返回值也可以返回任意类型的指针// 但是 niubiMeth()函数返回值      最终需要转换为具体类型指针才能使用。*/
void* niubiMeth(void* pVoid) {return pVoid;
}double  dou = 11.11;double* dp = &dou;// 但是 niubiMeth()函数返回值      最终需要转换为具体类型指针才能使用。double* resultPDou = static_cast<double *>(niubiMeth(dp));double  resultDou = *resultPDou;cout <<  "返回的结果 resultPDou ="<<resultPDou<<"  对应的数值resultDou ="<<resultDou << endl;//         返回的结果 resultPDou =0x99fec0  对应的数值resultDou =11.11

  

void*在C++中的作用其实就是为了实现泛型编程,和Java中使用Object来表示是一样的,所以又称为通用指针和泛指针,不过C++中大部分情况下会使用模板编程来实现泛型

	//C++中大部分情况下会使用模板编程来实现泛型。
template<typename  T>
T _say(T t) {return t;
}int main(){   /*模板编程不需要将强制转换为具体类型未强转也可以直接得出结果,这是因为模板编程会在编译器帮我们生成具体的函数。T _say(T t) {return t;}  ->  int* _say(int* t) {return t;}*/int i = 5;int* pi = &i;int* resultPI = _say(pi);cout << " *resultPI="<<*resultPI<< endl; // *resultPI=5float ff = 10.8;float* pff = &ff;float* resultPff = _say(pff);cout << " *resultPff ="<<*resultPff<< endl; //  *resultPff =10.8}

总结

1.void*是一个过渡型的指针状态,可以代表任意类型的指针,取值的时候需要转换为具体类型才能取值。其是处于数据类型顶端的状态:

2.void* 使用赋值运算符“=”赋值时,只能将具体类型赋值给void星,不能将void*赋值给具体类型。 

3.void*一般作为参数或者返回值来实现泛型编程,但是C++中一般考虑使用模板编程来实现。 

#include <iostream>
using namespace std;void say(int type, void* pVoid) {switch(type){case 0:{int* pInt = static_cast<int *>(pVoid);cout << "转为int类型的指针 pInt=" <<pInt <<" 对应的数值 *pInt="<<*pInt<< endl; //转为int类型的指针 pInt=0x99ff1c 对应的数值 *pInt=9527break;}case 1:{float* pFloat = static_cast<float *>(pVoid);cout << "转为float类型的指针 pFloat=" <<pFloat <<" 对应的数值 *pFloat="<<*pFloat<< endl;  //转为float类型的指针 pFloat=0x99ff10 对应的数值 *pFloat=23.3333break;}case 2:{double* pDouble = static_cast<double *>(pVoid);cout << "转为double类型的指针 pDouble=" <<pDouble <<" 对应的数值 *pDouble="<<*pDouble<< endl; //转为double类型的指针 pDouble=0x99ff10 对应的数值 *pDouble=9527.54break;}}};int say2( void* pVoid){int* pInt = static_cast<int *>(pVoid);cout << "转为int类型的指针 pInt=" <<pInt <<" 对应的数值 *pInt="<<*pInt<< endl;//转为int类型的指针 pInt=0x99ff1c 对应的数值 *pInt=9527return  *pInt-7;
}float say22( void* pVoid){float* pFloat = static_cast<float *>(pVoid);cout << "转为float类型的指针 pFloat=" <<pFloat <<" 对应的数值 *pFloat="<<*pFloat<< endl;//转为float类型的指针 pFloat=0x99ff10 对应的数值 *pFloat=23.3333return  *pFloat+10;
}void* say3(int type, void* pVoid) {switch(type){case 0:{int* pInt = static_cast<int *>(pVoid);cout << "转为int类型的指针 pInt=" <<pInt <<" 对应的数值 *pInt="<<*pInt<< endl; //转为int类型的指针 pInt=0x99ff1c 对应的数值 *pInt=9527return (void*)pInt;break;}case 1:{float* pFloat = static_cast<float *>(pVoid);cout << "转为float类型的指针 pFloat=" <<pFloat <<" 对应的数值 *pFloat="<<*pFloat<< endl;  //转为float类型的指针 pFloat=0x99ff10 对应的数值 *pFloat=23.3333return   (void*)pFloat;break;}case 2:{double* pDouble = static_cast<double *>(pVoid);cout << "转为double类型的指针 pDouble=" <<pDouble <<" 对应的数值 *pDouble="<<*pDouble<< endl; //转为double类型的指针 pDouble=0x99ff10 对应的数值 *pDouble=9527.54return   (void*)pDouble;break;}}
}/*void* pVoid 可以使用任意类型的实参指针类型返回值也可以返回任意类型的指针// 但是 niubiMeth()函数返回值      最终需要转换为具体类型指针才能使用。*/
void* niubiMeth(void* pVoid) {return pVoid;
}//C++中大部分情况下会使用模板编程来实现泛型。
template<typename  T>
T _say(T t) {return t;
}int main(){int number = 9527;say(0,&number);int resultInt =  say2(&number);cout <<  "返回的结果 resultInt="<<resultInt<< endl; //返回的结果 resultInt=9520int* resultPInt = static_cast<int *>(say3(0, &number));cout <<  "返回的结果 resultPInt="<<resultPInt<<"  对应的数值*resultPInt="<< *resultPInt << endl;  //返回的结果 resultPInt=0x99ff00  对应的数值*resultPInt=9527float f = 70.0/3.0;say(1,&f);float resultFloat = say22(&f);cout <<  "返回的结果 resultFloat="<<resultFloat<< endl;  //返回的结果 resultFloat=33.3333float *    resultPFloat = static_cast<float *>(say3(1, &f));cout <<  "返回的结果 resultPFloat ="<<resultPFloat<<"  对应的数值*resultPFloat="<< *resultPFloat << endl; //返回的结果 resultPFloat =0x99fef8  对应的数值*resultPFloat=23.3333double  d = 9527.54;say(2,&d);double*   resultPDouble = static_cast<double *>(say3(2, &d));cout <<  "返回的结果 resultPDouble ="<<resultPDouble<<"  对应的数值*resultPDouble="<< *resultPDouble << endl; //返回的结果 resultPDou =0x99fed8  对应的数值*resultPDou=11.11double  dou = 11.11;double* dp = &dou;// 但是 niubiMeth()函数返回值      最终需要转换为具体类型指针才能使用。double* resultPDou = static_cast<double *>(niubiMeth(dp));double  resultDou = *resultPDou;cout <<  "返回的结果 resultPDou ="<<resultPDou<<"  对应的数值resultDou ="<<resultDou << endl;//         返回的结果 resultPDou =0x99fec0  对应的数值resultDou =11.11int i = 5;int* pi = &i;void* pv = pi;//cout << *pv << endl;//表达式必须是指向完整对象类型的指针int*  pip =  (int*)pv;cout << " *pip="<<*pip << endl;  // *pip=5/*模板编程不需要将强制转换为具体类型未强转也可以直接得出结果,这是因为模板编程会在编译器帮我们生成具体的函数。T _say(T t) {return t;}  ->int* _say(int* t) {return t;}float* _say(float* t) {return t;  }*/int* resultPI = _say(pi);cout << " *resultPI="<<*resultPI<< endl; // *resultPI=5float ff = 10.8;float* pff = &ff;float* resultPff = _say(pff);cout << " *resultPff ="<<*resultPff<< endl; //  *resultPff =10.8return  0;
}

相关文章:

如何理解C++中的void*

1.什么是void* 首先void*中的void代表一个任意的数据类型&#xff0c;"星号"代表一个指针&#xff0c;所以其就是一个任意数据类型的指针。 其实就是一个未指定跳跃力的指针。 那void*的跳跃力又什么时候指定&#xff1f;在需要使用的时候指定就可以了&#xff0c…...

MVC,MVP,MVVM的理解和区别

MVC MVC &#xff0c;早期的开发架构&#xff0c;在安卓里&#xff0c;用res代表V&#xff0c;activity代表Controller层&#xff0c;Model层完成数据请求&#xff0c;更新操作&#xff0c;activity完成view的绑定&#xff0c;以及业务逻辑的编写&#xff0c;更新view&#xf…...

【TypeScript】一直提示 :无法重新声明块范围变量

【TypeScript】一直提示 &#xff1a;无法重新声明块范围变量 问题描述&#xff1a;在VSCode中编写ts代码时&#xff0c;编写保存完之后&#xff0c;通过tsc 文件名.ts编译就会看到变量名下面出现了红色的波浪线&#xff0c;提示的内容是无法重新声明块范围变量。 解决方法&am…...

【python自动化】七月PytestAutoApi开源框架学习笔记(一)

前言 本篇内容为学习七月大佬开源框架PytestAutoApi记录的相关知识点&#xff0c;供大家学习探讨 项目地址&#xff1a;https://gitee.com/yu_xiao_qi/pytest-auto-api2 阅读本文前&#xff0c;请先对该框架有一个整体学习&#xff0c;请认真阅读作者的README.md文件。 本文…...

Python学习 -- logging模块

logging 模块是 Python 中用于记录日志的标准库&#xff0c;它提供了丰富的功能&#xff0c;可以帮助开发者进行日志记录和管理。以下是关于logging模块的详细使用方式&#xff0c;包括日志级别、处理流程、Logger 类、Handler 类、Filter 类、Formatter 类以及模块中常用函数等…...

【socket】getaddrinfo、getsockname、getpeername对比

这三个函数都是在网络编程中用来获取地址信息的&#xff0c;但是它们的使用场景和功能有所不同。getaddrinfo(): 这个函数主要用于将一个主机名&#xff08;或者 IP 地址&#xff09;和端口号转换成适用于 socket() 函数的一个或多个套接字地址结构。它能够处理 IPv4 和 IPv6 地…...

【MySQL】表的增删改查(进阶)

表的增删改查&#xff08;进阶&#xff09; 一. 数据库约束1. 约束类型2. NULL约束3. UNIQUE&#xff1a;唯一约束4. DEFAULT&#xff1a;默认值约束5. PRIMARY KEY&#xff1a;主键约束6. FOREIGN KEY&#xff1a;外键约束7. CHECK约束 二. 表的设计1. 一对一2. 一对多3. 多对…...

关于安卓13中Android/data目录下的文件夹只能查看无法进行删改的问题

前言 因为升级了安卓13&#xff0c;然后有个app需要恢复数据&#xff0c;打算和以前一样直接删除Android/data下对应目录再添加&#xff0c;结果不行&#xff0c;以下是结合网上以及自己手机情况来做的一种解决方案。 解决 准备&#xff1a; 待恢复app&#xff08;包名com.…...

Vulnhub: Masashi: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.236 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.236查看80端口的robots.txt提示三个文件 snmpwalk.txt内容&#xff0c;tftp服务在1337端口 sshfolder.txt内容&#xff0c…...

校园二手物品交易系统微信小程序设计

系统简介 本网最大的特点就功能全面&#xff0c;结构简单&#xff0c;角色功能明确。其不同角色实现以下基本功能。 服务端 后台首页&#xff1a;可以直接跳转到后台首页。 用户信息管理&#xff1a;管理所有申请通过的用户。 商品信息管理&#xff1a;管理校园二手物品中…...

Pixillion Pro for Mac:将您的图像转换为艺术佳作

Pixillion for Mac有着非常强大的图像转换功能和简单的使用方法&#xff0c;帮助你快速完成大批量图像转换的工作&#xff0c;支持一键转换jpeg、jpg、bmp、png、gif、raf、heic等各种格式的图像文件&#xff0c;同时pixillion mac激活版还提供了图像旋转、添加水印、调整图像大…...

【上海迪士尼度假区】技术解决方案

开源平台地址Giteehttps://gitee.com/issavior/disney 技术解决方案 1. 背景2. 技术架构3. 业务架构3.1 架构图3.2 说明 4. 技术能力4.1 自研中间件4.2 定制化中间件 5. 领域模型6. 数据模型7. 交易链路8. 状态机8. 接口文档 1. 背景 上海迪士尼度假区已运营近10年&#xff0c…...

每日刷题-2

目录 一、选择题 二、编程题 1、倒置字符串 2、排序子序列 3、字符串中找出连续最长的数字串 4、数组中出现次数超过一半的数字 一、选择题 1、 题目解析&#xff1a; 二维数组初始化的一般形式是&#xff1a; 数据类型 数组名[常量表达式1][常量表达式2] {初始化数据}; 其…...

AOSP内置搜狗输入并设置默认输入法

前期准备 AOSP分支&#xff1a;aosp13_r7 系统版本&#xff1a;Ubuntu 22.04.1 LTS 工具&#xff1a;手&#xff0c;vscode&#xff0c;winscp(因为我是用的服务器编译) 下载搜狗输入法 思路&#xff1a; 1.集成搜狗输入法到aosp 2.删除系统输入法 3.设置搜狗输入法为默…...

ICCV 2023|通过慢学习和分类器对齐在预训练模型上进行持续学习

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 作者介绍 张耕维 悉尼科技大学在读博士生&#xff0c;研究方向为持续学习 报告题目 通过慢学习和分类器对齐在预训练模型上进行持续学习 内容简介 持续学习研究的目标在于提高模型利用顺序到达的数据进行学习的…...

蓝桥杯打卡Day5

文章目录 日志排序重复者 一、日志排序IO链接 本题思路:本题就是根据就是排序的知识点&#xff0c;在sort内部可以使用仿函数来改变此时排序规则。 #include <bits/stdc.h>const int N10010; int n; std::string logs[N];int main() {std::ios::sync_with_stdio(false)…...

QT for andriod

QT for andriod 开发 apk软件&#xff0c;因为一些特殊的原因&#xff0c;在这里简单的记录一哈自己开发apk的流程和心得。 首先说明我采用的环境有哪些&#xff1f; 1、QT的版本&#xff0c;个人建议5.15.2的版本及以上&#xff0c;我是用的5.15.2。 2、andriod studio 可以…...

【广州华锐互动】AR技术在配电系统运维中的应用

随着科技的不断发展&#xff0c;AR(增强现实)技术逐渐走进了我们的生活。在电力行业&#xff0c;AR技术的应用也为巡检工作带来了许多新突破&#xff0c;提高了巡检效率和安全性。本文将从以下几个方面探讨AR配电系统运维系统的新突破。 首先&#xff0c;AR技术可以实现虚拟巡检…...

TiDB 一栈式综合交易查询解决方案获“金鼎奖”优秀金融科技解决方案奖

日前&#xff0c;2023“金鼎奖”评选结果揭晓&#xff0c; 平凯星辰&#xff08;北京&#xff09;科技有限公司研发的 TiDB 一栈式综合交易查询解决方案获“金鼎奖”优秀金融科技解决方案奖 &#xff0c; 该方案已成功运用于 多家国有大行、城商行和头部保险企业 。 此次获奖再…...

《网络是怎样连接的》(六)

本文主要取材于 《网络是怎样连接的》 第六章。 目录 6.1 服务器概览 6.2 服务器的接收操作 6.3 Web服务器程序解释请求消息并作出响应 6.4 浏览器接收响应消息并显示内容 简述&#xff1a;本文主要内容是解释 网络包到达服务器之后&#xff0c;如何给客户端响应的。 服务…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...