【c语言】void* 详解与应用

c++中的void* 今天看到一段代码,觉得非常有意思。 void* say_hello(void* args) { cout << "Hello World!" << endl; return 0; } 这里的返回类型竟然是void*。一般来说如果没有返回值,那么写一个void就行了,void*到底是什么样的存在?所以做了一些测试,总结了一些void*指针的... 阅读详情
AI摘要

本文详细介绍了C语言中void和void*的关键概念,包括void作为函数参数和返回值的使用,void*指针的灵活性及其在内存操作函数中的应用,同时讨论了void*的使用规则和注意事项。,

前言

void 在英文中作为名词的解释为 “空间,空白,空虚”,在 C 语言中,void 被翻译为"无类型",相应的void * 为"无类型指针"。

void 似乎只有"注释"和限制程序的作用,当然,这里的"注释"不是为我们人提供注释,而是为编译器提供一种所谓的注释。

1.常见void 与void* 应用

1.1.void 作为函数参数类型的示例:

void printMessage(const char* message) {
    printf("%s\n", message);
}

在这个例子中,函数 printMessage 接收一个 const char* 类型的参数,该参数表示一个字符串。函数并不需要返回值,因此返回类型为 void。

1.2.void* 类型作为函数返回值:

void* allocateMemory(size_t size) {
    return malloc(size);
}

在这个例子中,函数 allocateMemory 接收一个 size_t 类型的参数,表示需要分配的内存大小。函数使用 malloc 函数动态分配内存,并将返回的指针类型转换为 void*,然后返回。

1.3.void* 指针的使用示例:

int num = 10;
void* ptr = &num;
int* intPtr = (int*)ptr;
printf("%d\n", *intPtr);  // 输出 10

在这个例子中,整数 num 被创建,并通过 & 运算符获取其地址。然后,将该地址存储在 void* 类型的指针 ptr 中。通过使用 (int*) 运算符将 ptr 转换为 int* 类型的指针 intPtr,可以访问并输出该整数的值。

1.4.void 作为函数指针的示例:

void (*funcPtr)() = &greet;
funcPtr();  // 调用函数指针

在这个例子中,声明了一个名为 funcPtr 的函数指针,它可以指向不返回任何值的函数。然后将 greet 函数的地址赋值给 funcPtr,最后通过函数指针调用函数。

1.5.void* 类型的数组示例:

void* arr[3];
int num = 10;
char ch = 'A';
float f = 3.14;

arr[0] = &num;
arr[1] = &ch;
arr[2] = &f;

printf("%d\n", *(int*)arr[0]);     // 输出 10
printf("%c\n", *(char*)arr[1]);    // 输出 A
printf("%f\n", *(float*)arr[2]);   // 输出 3.14

在这个示例中,函数 printValue 接收一个 void* 类型的参数以及一个代表数据类型的整数参数。根据传入的类型,在函数内部使用合适的类型转换将 void* 指针解引用,并打印相应的值。

2.void和void*的使用规则

2.1. void* 指针可以指向任意类型的数据

可以指向任意类型的数据,就是说可以用任意类型的指针对 void* 指针对 void* 指针赋值。例如:

int* a;
void* p;
p = a;

如果要将 void* 指针 p 赋给其他类型的指针,则需要强制类型转换,就本例而言:a=(int *)p。在内存的分配中我们可以见到 void* 指针使用:内存分配函数 malloc 函数返回的指针就是 void * 型,用户在使用这个指针的时候,要进行强制类型转换,也就是显式说明该指针指向的内存中是存放的什么类型的数据 (int *)malloc(1024) 表示强制规定 malloc 返回的 void* 指针指向的内存中存放的是一个个的 int 型数据。

2.2. void* 指针不允许进行 ++ 或 -- 操作

在 ANSI C 标准中,不允许对 void* 指针进行一些算术运算如 p++ 或 p+=1 等,因为既然 void 是无类型,那么每次算术运算我们就不知道该操作几个字节,例如 char 型操作 sizeof(char) 字节,而 int 则要操作 sizeof(int) 字节。( 而在 GNU 中则允许,因为在默认情况下,GNU 认为 void * 和 char * 一样,既然是确定的,当然可以进行一些算术操作,在这里sizeof(*p)==sizeof(char)。 )
在这里插入图片描述

2.3.void类型定义

void 几乎只有"注释"和限制程序的作用,因为从来没有人会定义一个 void 变量,让我们试着来定义:

void a;

在这里插入图片描述

这行语句编译时会出错。即使 void a 的编译不会出错,它也没有任何实际意义。

2.4.void*指针的互相赋值

众所周知,如果指针 p1 和 p2 的类型相同,那么我们可以直接在 p1 和 p2 间互相赋值;如果 p1 和 p2 指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。

float *p1;
int *p2;
p1 = p2;

在C语言中,指针之间的赋值会受到类型的限制。然而,在某些情况下,不同类型的指针可以进行隐式转换,并且编译器不会报错。
在您提供的代码中,将一个 int* 类型的指针 p2 赋值给一个 float* 类型的指针 p1。虽然 p1 和 p2
的指针类型不同,但由于 float 和 int 都是基本数据类型,且其大小相同,因此编译器允许将 int* 类型指针赋给 float*
类型的指针。这种隐式转换被称为兼容指针类型的转换。 请注意,虽然这样的赋值在语法上是合法的,但它可能导致难以预测的行为和错误的结果。由于
float 和 int 的内存布局是不同的,使用错误类型的指针可能会导致解释存储在其指向的内存位置上的值时出现问题。
因此,为了代码的可读性和可维护性,通常建议遵循类型的匹配性,不要使用不同类型的指针进行赋值,除非进行明确的类型转换。这样可以避免潜在的错误和问题。

所以最好写成:

float *p1;
int *p2;
p1 = (float *)p2;

而 void * 则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换。

void *p1;
int *p2;
p1 = p2;

但这并不意味着,void * 也可以无需强制类型转换地赋给其它类型的指针。因为"无类型"可以包容"有类型",而"有类型"则不能包容"无类型"。

2.5.小心使用void*指针类型

按照 ANSI(American National Standards Institute) 标准,不能对 void 指针进行算法操作,即下列操作都是不合法的:

void * pvoid;
pvoid++; //ANSI:错误
pvoid += 1; //ANSI:错误
//ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
//例如:
int *pint;
pint++; //ANSI:正确
//pint++ 的结果是使其增大 sizeof(int)。

在实际的程序设计中,为迎合 ANSI 标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:

void * pvoid;
((char *)pvoid)++; 
(char *)pvoid += 1; 

需要注意的是,不能写成:

(char*)pvoid++;  //err

在这里插入图片描述

因为++会先与pvoid结合!

3.void*指针所带来的好处

函数中形为指针类型时,我们可以将其定义为 void 指针,这样函数就可以接受任意类型的指针。如:
典型的如内存操作函数 memcpy 、 memmove 和 memset等等的函数:

void * memcpy ( void * destination, const void * source, size_t num );
void * memmove ( void * destination, const void * source, size_t num );
void * memset ( void * ptr, int value, size_t num );

这样,任何类型的指针都可以传入 memcpy 、 memmove 和 memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型( 泛型编程)。如果memcpy 、 memmove 和 memset的参数类型不是 void *,而是 char *,那才叫真的奇怪了!这样的 memcpy 、 memmove 和 memset明显不是一个"纯粹的,脱离低级趣味的"函数!void 的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中"抽象基类"的概念,也很容易理解 void 数据类型。正如不能给抽象基类定义一个实例,我们也不能定义一个 void(让我们类比的称 void 为"抽象数据类型")变量。

  • 参考文章地址:http://www.cnblogs.com/archimedes/p/c-void-point.html
C++ 编程基础练习——void型的函数定义 请给出一个void函数的定义,该函数有三个int类型的形参,并将这三个数的乘积输出到屏幕上。编写一个完整的程序对该函数进行测试。 #include <iostream> using namespace std; void multiply (int& a,int& b,int& c); // 按引用传递,& 与int之间没有空格,与a之间空一格; // 在函数声明和定义时要写&,在调用函数时不用写&; // 函数声明时要写分号 int main() 阅读详情

相关推荐

SAP 物料主数据中 Base Unit of Measure 的变更逻辑与落地检查

摘要:SAP物料主数据中的Base Unit of Measure(基本计量单位)并非普通字段,它关联库存、采购、销售等核心业务数据。官方建议在物料创建初期慎重选择该单位,因其变更将影响历史业务数据的语义一致性。系统对修改设有严格限制:库存必须为零,且无相关采购订单等未清业务。实际项目中,更推荐使用替代计量单位而非直接修改基础单位,以避免数据断层风险。变更前需全面检查相关业务对象,并建立完善的治理流程。(149字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1万+

C语言中void的高级应用

C语言中的void 高级运用

wwwqqq2014的博客 1万+

一文讲清CAN和CANFD的区别

本文将从技术原理、协议特性到应用场景,深度解析两者的核心差异。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 3204

void的使用

void的使用

smallredhat01的博客 5728

VulnHub系列之BadStore_123渗透测试

BADSTORE: 1.2.3 早期网商系统漏洞鉴赏(2004)

Flynn的博客 1628

[OrCad电路板设计系统].Orcad.Pspice.9.2下载安装

Orcad.Pspice.9.2详细下载安装图文步骤1 安装前准备工作1.1 下载安装包1.2 解压2 安装时步骤2.1 安装文件2.2 破解文件3 安装完成 1 安装前准备工作 1.1 下载安装包 打开百度网盘APP 链接:https://pan.baidu.com/s/1cMFxHUvuh5iEhFVT-lvciQ 提取码:7m65 1.2 解压 解压下载好的安装包 2 安装时步骤 2.1 安装文件 1.点击Setup安装文件,出现警告对话框,告诉你应该关闭所有病毒防火墙,点击确定 2.进入安装界面,

weixin_48924581的博客 1万+

C语言中void*详解及应用

void在英文中作为名词的解释为“空虚;空间;空隙”;而在C语言中,void被翻译为“无类型”,相应的void *为“无类型指针”。void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为我们人提供注释,而是为编译器提供一种所谓的注释。 本文地址:http://www.cnblogs.com/archimedes/p/c-void-point.html,转载请注明源地址。 void的作...

houzhizhen的专栏 2万+

海外最新AI营销AI销售书籍推荐AI营销培训讲师AI销售培训讲师人工智能营销培训师人工智能销售培训师AI赋能营销培训AI赋能销售培训企业AI营销内训企业AI销售内训AI营销课程讲师AI销售课程讲师

专栏|AI营销与AI销售实战 · 第46期在这个人类与算法共舞的时代,销售,已经不是你我熟悉的那个“打电话、见客户、做PPT”的老行当了。你还以为销售是“打感情牌”?错了,情感要继续,但方式已经升级。你还以为AI只是“写写文案”?错了,文案只是皮毛,真正的杀器,是思维方式的重构,是认知地图的重绘。首先,我们需要明确一个事实:AI并不会消灭销售这个职业,但它必然会重新定义销售的本质。在销售领域,真正的制胜之道不是简单地采用AI工具,而是的能力。

Akibfrycc的博客 1100

C 语言中 void* 详解及应用

在C语言中void被翻译为无类型,那么void* 翻译为无类型指针。 void作用:对函数返回的限定和对参数返回的限定 1. 当函数不需要返回值时: void func(int a,int b) 2. 当函数不需要参数时: void func(void) void 修饰指针使用规则 void 指针可以指向任意类型的数据,就是说可以用任意类型的指针对 void 指针对 void 指针赋值。例如: int *a; void *p; p=a; 我有一篇文章写过内存分配malloc和f.

Bobowen的博客 4896

零基础玩转华为AP 4050DN-HD:FAT模式家庭无线网络配置实战

本文为零基础用户提供华为AP 4050DN-HD从FIT模式转换为FAT模式的完整实战教程。详细介绍了固件升级、模式转换以及配置家庭无线网络(包括路由、DHCP、Wi-Fi和NAT)的每一步操作,帮助用户将企业级瘦AP改造为高性能家庭胖AP,打造稳定可靠的家庭网络环境。

weixin_29196613的博客 628

【机器学习|评价指标8】混淆矩阵(Confusion Matrix)、Cohen‘s Kappa 系数、详解,平均交并比(mIoU)、列联表(Contingency Table)附代码。

【机器学习|评价指标8】混淆矩阵(Confusion Matrix)、Cohen's Kappa 系数、详解,平均交并比(mIoU)、列联表(Contingency Table)附代码。

2401_89898861的博客 1424

c语言中void应用,C语言中void*详解及应用

void在英文中作为名词的解释为“空虚;空间;空隙”;而在C语言中,void为“无类型”,相应的void*为“无类型指针”。void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为我们人提供注释,而是为编译器提供一种所谓的注释。void的作用:1.对函数返回的限定,这种情况我们比较常见。2.对函数参数的限定,这种情况也是比较常见的。一般我们常见的就是这两种情况:当函数不需要返回值值时,...

weixin_28997071的博客 627

XCP实战系列介绍09-基于Vehicle Spy进行XCP测量步骤详解

详细介绍如何使用Vehicle Spy进行XCP测量

initiallizer的博客 1391

C语言中 void* 详解及应用

void在英文中作为名词的解释为“空虚;空间;空隙”;而在C语言中,void被翻译为“无类型”,相应的void *为“无类型指针”。void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为我们人提供注释,而是为编译器提供一种所谓的注释。 本文地址:http://www.cnblogs.com/archimedes/p/c-void-point.html,转载请注明源地址。 void的作用: 1.对函数返回的限定,这种情况我们比较常见。 2.对函数参数的限定,这种情况也是比较常见的。 一般我们常见

weixin_42692164的博客 950

HQChart实战教程64-自定义分时图标题栏

分时图标题栏显示的是当前十字光标所在位置的分钟信息,显示在分时图窗口顶部。一般会显示品种的名称,日期,时间,价格,均价 涨幅,成交量,金额等等,hqchart内置会显示这些信息。如果要额外显示其他的字段,就需要通过替换格式化标题输出函数来是现实。我们在hqchart实例创建完成以后,通过OnCreatedCallback回调函数替换自己的格式化输出函数。返回 { AryText:[ { Text:文字, Color:颜色},…入参 data={ Data: 当前十字光标所在位置的分钟线 }

小银 1055

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

c语言void结尾,C语言中void*详解及应用

void在英文中作为名词的解释为“空虚;空间;空隙”;而在C语言中,void被翻译为“无类型”,相应的void *为“无类型指针”。void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为我们人提供注释,而是为编译器提供一种所谓的注释。void的作用:1.对函数返回的限定,这种情况我们比较常见。2.对函数参数的限定,这种情况也是比较常见的。一般我们常见的就是这两种情况:当函数不需要返回...

weixin_29327525的博客 797

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C 语言中 void* 详解及应用介绍

void 在英文中作为名词的解释为 "空虚、空间、空隙",而在 C 语言中,void 被翻译为"无类型",相应的void * 为"无类型指针"。void 似乎只有"注释"和限制程序的作用,当然,这里的"注释"不是为我们人提供注释,而是为编译器提供一种所谓的注释。 void 的作用 对函数返回的限定,这种情况我们比较常见。 对函数参数的限定,这种情况也是比较常见的。 一般我们常见的就是这两种情况: 当函数不需要返回值值时,必须使用void限定,这就是我们所说的第一种情况。例如:void func

Free雅轩的博客 426

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: 【C语言】 指针和数组中 sizeof与strlen 的特殊处理
下一篇: 【C语言】#include<string.h>
Q_hd
Q_hd 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄6年 2058粉丝 194原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q_hd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值