深入理解C语言的void*

2025-01-20 16:50
文章标签 深入 语言 理解

本文主要是介绍深入理解C语言的void*,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下...

一、void* 的类型任意性

void* 是一种通用指针类型。它可以指向任意类型的数据。例如,它可以指向一个整数(int)、一个浮点数(float)、一个字符(char)或者一个结构体等。在C语言中,当你使用void*指针时,你不需要在编译时指定它将指向的数据类型。这使得void* 在一些China编程需要通用指针的场景下非常有用,比如在内存分配函数malloc中返回的就是void*类型的指针。因为malloc函数不知道用户将要分配的内存用于存储哪种类型的数据,所以它返回一个void*指针,用户可以根据自己的需要将其转www.chinasem.cn换为特定类型的指针。
例如:

void* ptr = malloc(10 * sizeof(int));
int* intPtr = (int*)ptr;  // 将void*指针转换为int*指针

在这个例子中,void*指针 ptr 可以指向分配的内存区域,然后通过类型转换将其转换为int*指针,用于存储整数数组。

二、编译器对 void* 的类型检查

编译时不做类型检查(针对void*本身)编译器在编译时不会对void*指针本身进行类型检查。因为 void* 表示“未知类型”的指针,编译器无法知道它实际指向的数据类型。所以,当你对void指针进行操作(如赋值等)时,编译器不会检查其指向的数据类型是否正确。例如,你可以将一个指向整数的指针赋值给void指针,也可以将一个指向字符的指针赋值给void*指针,编译器都不会报错。

int a = 10;
char b = 'k';
void* vp1 = &a;
void* vp2 = &b;

在这个例子中,vp1和vp2都是void*指针,分别指向了不同类型的变量a和b,编译器不会对这www.chinasem.cn种赋值操作进行类型检查。

三、需要显式类型转换

当你想要使用 void* 指针访问其中的某个值时,通常需要先将其转换为特定类型的指针,然后通过转换后的指针来访问值。在转换时,你需要明确指定目标类型,编译器会对转换后的指针类型进行检查。例如,如果你想通过 void* 指针访问一个整数的值,你需要先将其转换为 int* 指针。
例如:

void* vp = malloc(sizeof(int));
*(int*)vp = 20;  // 先将void*转换为int*,然后通过int*指针赋值

在这个例子中,vp是一个void*指针,指向分配的内存。在给这块内存赋值之前,需要先将其转换为int*指针。如果转换的目标类型和实际存储的数据类型不匹配,可能会导致运行时错误。 比如,如果这块内存实际上存储的是一个浮点数,而你将其转换为int*指针并访问,可能会得到错误的结果或者引发程序异常。编译器在转换时会检查语法是否正确(如是否有合适的类型转换操作),但对于类型转换的正确性(即是否符合程序的实际逻辑)主要依赖于程序员的正确使用。

占用的字节

一、32位系统
在32位系统中,void* 指针通常占据4个字节。这是因为32位系统中的内存地址空间是2的32次方(即android4GB),用4个字节(32位)就可以表示一个内存地址。例如,在一个32位的Windows系统或者32位的linux系统上,无论是void指针,还是其他类型的指针(如int、char*等),它们都占据4个字节。这4个字节存储的是一个内存地址,这个地址可以指向进程地址空间内的任意位置。

二、64位系统
在64位系统中,void* 指针通常占据8个字节。64位系统有更大的内存地址空间,理论上可以达到2的64次方字节。因此,需要用8个字节(64位)来表示一个完整的内存地址。在64位系统上,无论是 void* 指针,还是其他类型的指针,它们的大小都是8个字节。这使得64位系统能够访问更大的内存空间,支持更大的数据处理和更复杂的程序运行。

四、总结

通过我们上面的介绍, 我们发现 void* 在 C 语言中是经常使用的, 它主要有下面这几个方案:

  • 第一个方案就是作为结构体的字段, 这样我们可以去表示对应的范型字段
  • 函数的参数, 或者返回值, 但是我觉得这种最好少用, 因为导致对应的接口不够明确
  • 各种内存相关的函数, 这其实就是一个很奇妙的东西, 因为在操作系统级别, 我们并不知道这块内存到底是什么类型的变量

约定: 当我们在使用 void* 的时候, 我们最好弄清楚当前这个指针指向的信息, 可以通过明确的变量名来完成

到此这篇关于深入理解C语言的void*的文章就介绍到这了,更多相关C语言 void*内容请搜索China编程(www.cppcpythonns.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于深入理解C语言的void*的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153144

相关文章

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言