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

嵌入式初学-C语言-二四

Void与void*的区别

定义:

Void:空类型,是数据类型的一种

Void*:是指针类型,是指针类型的一种,可以匹配任何类型的指针,类似于通配符

Void

说明:void作为返回值类型使用,表示没有返回值,作为参数,表示形参列表为空,在调用函数时不能给实参

// 函数声明
void fun(void); // 等效于 void fun();
// 函数调用
fun();

Void*

说明:

  1. void*是一个指针类型,但是该指针的数据类型是不明确的,无法通过解引用获取内存中的数据,因为void*不知道访问几个内存单元
  2. void*是一种数据类型,可以作为函数返回值类型,也可以作为形参类型
  3. void*类型的变量在使用之前必须强制类型转换
int *p = (int*)malloc(4);
double *p2 = (double*)malloc(8);

举例:

#include <stdio.h>
#include <stdlib.h>
// 函数定义
void* fun(void* p) // 指针函数(返回值类型是指针的函数,此时返回的是不明确类型,需要外部强转)
{
int *p;
// double *p;
// long *p;
// char *p;
return p;
}
// 函数调用
void main()
{
int *p;
void* a = fun(p);// 这种接收方式,实际上没有意义
printf("%p\n",a);// 可以正常打印,打印出一个地址
*a = 10;// 编译报错,void*变量不能解引用访问数据
int *w = (int*)a;
*w = 10;// 编译和运行正常,void*变量a在使用前已经强制类型转换了,数据类型明确了,访问的内存
单元明确了。
}

说明:

  1. void*作为返回值类型:这个函数可以返回任何类型(char*  int*  double*)的指针
  2. void*作为形参的类型:这个函数在调用时,可以给任意类型的指针

总结:

  1. void*类似于通配符,不能对void*类型的变量解引用(因为不明确内存单元的大小)
  2. void*在间接访问(解引用)前要强制类型转换,但不能太随意,否则存和取的数据类型不一致

内存操作

我们对于内存的操作借助于string.h这个库提供的内存操作函数。

内存填充

头文件:#include<string.h>

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

函数功能:填充s开始的堆内存前n个字节,使得每个字节值为c

函数参数:

  1. void*s:待操作内存的首地址
  2. int c:填充的字节数据
  3. size_t n:被填充的字节数

返回值:返回s

注意:c常常设置为0,用于动态内存初始化

/**
* 内存操作函数-memset
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test1()
{
// 在堆内存申请了一块存储空间
int *p = (int*)malloc(4 * sizeof(int));
if(!p)
{
puts("内存分配失败!");
return;// 后续代码不需要执行
}
// 给这块内存进行初始化操作(填充)
memset(p,0, 4 * sizeof(int));
printf("%d\n",*(p+1));
// 内存使用完毕,进行回收
free(p);
p = NULL;
}
int main()
{
test1();
return 0;
}

内存拷贝

头文件:#include<string.h>

函数原型:

  1. void*memcpy(void*dest,const void*src,size_t n);适合目标地址与源地址内存无重叠的情况
  2. void*memmove(void*dest,const void*src,size_t n);

函数功能:拷贝src开始的堆内存空间前n个字节到dest对应的内存中

函数参数:

  1. void*dest:目标内存的首地址
  2. void* src:源内存首地址
  3. size_t n:被拷贝的字节数

返回值:返回dest

注意:内存申请了几个内存空间就访问几个内存空间,否则数据不安全

注意:memcpy与memmove一般情况下是一样的,更建议使用memmove进行内存拷贝因为mememove函数是从自适应(从后往前,从前往后)拷贝,当我们被拷贝的内存和目的地的内存有重叠时数据不会出现拷贝错误,而memecpy函数是从前往后拷贝,当被拷贝的内存和目的地有重叠时数据会出现拷贝错误

/**
* 内存操作函数-memcpy|memmove
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test1()
{
// 申请内存
// int *p1 = (int*)malloc(4 * sizeof(int));
// int *p2 = (int*)malloc(6 * sizeof(int));
// 给p1,p2填充数据,可以使用for循环..
// for(int i = 0; i < 4; i++)
// p1[i] = 10 + i;
// memset(p2,0,6 * sizeof(int));
// 创建数组
int p1[4] = {11,12,13,14};
int p2[6] = {21,22,23,24,25,26};
// 将p1中的数据通过内存拷贝函数,拷贝到p2
// memcpy(p2+2,p1+1,2*sizeof(int)) // int p2[6] = {21,22,12,13,25,26}
memmove(p2+2,p1+1,2*sizeof(int));
// 测试输出数组
for(int i = 0; i < 4; i++)
printf("%4d",p1[i]);
printf("\n");
for(int j = 0; j < 6; j++)
printf("%4d",p2[j]);
printf("\n");
// 如果使用手动分配的指针,一定要记得释放内存
// free(p1);
// free(p2);
// p1 = NULL;
// p2 = NULL;
}
int main()
{
test1();
return 0;
}

内存比较

头文件:#include<string.h>

函数原型:int memcmp(void*dest,const void*src,size_t n)

函数功能:比较src和dest所代表的内存前n个字节数据

函数参数:

  1. void*dest:目标内存首地址
  2. const void*src:源内存首地址
  3. size_t n:比较的字节数

返回值:

  1. 0:数据相同
  2. >0:dest中的数据大于src(目标大于源)
  3. <0:dest中的数据小于src

注意:n一般和src,dest的总容量一样,如果不一样内存比较的结果就不确定

案例:

/**
* 内存操作-memcmp
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test1()
{
// 申请内存
int *p1 = (int*)malloc(3*sizeof(int));
int *p2 = (int*)malloc(4*sizeof(int));
// int p1[4] = {1,0,3,6};
// int p2[4] = {1,2,3,4};
// int result = memcmp(p1,p2,4*sizeof(int));
*p1 = 65;
*p2 = 70;
char *a = (char*)p1;// 类型转换
char *b = (char*)p2;
printf("%c,%c\n",*a,*b);
int result = memcmp(a+1,b+1,1*sizeof(char));
printf("%d\n",result);
}
int main()
{
test1();
}

内存查找

头文件:#include<string.h>

函数原型:void *memrchr | *memchr(const void *s, int c, size_t n);

函数功能:在s开始的堆内存空间前n个字节中查找字节数据c

函数参数:

  1. const void *s:待操作内存首地址;
  2. int c:待查找的字节数据
  3. size_t n:查找的字节数

返回值:返回查找到的字节数据地址

注意:如果内存中没有重复数据,memchr和memrchr结果是一样的,若果有重复数据memchr和memrchr结果就不一样

案例:

/**
* 内存操作-memchr | memrchr
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 声明外部函数
extern void *memrchr(const void *s,int c,size_t n);
void test1()
{
// 申请内存
int *p = (int*)malloc(4*sizeof(int));
if(!p)
{
puts("内存分配失败!");
return;
}
// 给变量赋值
for(int i = 0; i < 4; i++)
{
p[i] = i * 2;
}
p[3] = 4;
// 输出
for(int i = 0; i < 4; i++)
{
printf("%d,",p[i]);
}
printf("\n");
// 内存查找 memchr
int *x = (int*)memchr(p,4,4*sizeof(int));
printf("%p--%p--%d\n",x,p,*x);
// 内存查找 memrchr
int *y = (int*)memrchr(p,4,4*sizeof(int));
printf("%p--%p--%d\n",y,p,*y);
// 回收内存
free(p);
p = NULL;
}
int main()
{
test1();
}

本章小结

1.  指针就是地址。变量的指针就是变量的地址。指针变量就是地址变量。

     指针是地址本身,指针变量是用来存放地址的变量。

2.  指向   把谁的地址存放在指针变量中,该指针变量就指向谁

3.  深入掌握对数组操作中怎样正确使用指针。

4.  有关指针变量的定义形式归纳比较,见表8-4。

5.  指针运算小结

  ① 指针变量加(减)一个整数

       p++、p--、p+i、p-i、p+=i、p-+i 等均使指针变量p加(减)一个整数。改变了指向的地址值。

  ②  指针变量赋值 

         不要把一个整型数赋给指针变量

   ③  指针变量可以赋空值

          p=NULL    即不指向任何变量

   ④  两个指针变量可以相减

         两个指向同一数组的指针变量可以相减,得到两个指针之间元素的个数,但相加无意义

   ⑤  两个指针变量比较

         两个指向同一数组的指针变量可以比较,指向前面元素的指针“小于”指向后面元素的指针变量

相关文章:

嵌入式初学-C语言-二四

Void与void*的区别 定义&#xff1a; Void&#xff1a;空类型&#xff0c;是数据类型的一种 Void*&#xff1a;是指针类型&#xff0c;是指针类型的一种&#xff0c;可以匹配任何类型的指针&#xff0c;类似于通配符 Void 说明&#xff1a;void作为返回值类型使用&#xf…...

tcpdump入门——每种flag分别表示什么意思

在 tcpdump 的输出中&#xff0c;TCP 标志位&#xff08;Flags&#xff09;通常用简写字符表示。以下是每种 TCP 标志位的含义及其对应的简写字符&#xff1a; TCP 标志位及其简写 SYN (Synchronize) 作用&#xff1a;用于初始化连接。简写字符&#xff1a;S ACK (Acknowledgm…...

Qt如何封装工具

在Qt中封装工具类或库是一种常见的开发模式&#xff0c;通过封装可以提高代码的可重用性、可维护性和模块化。以下是封装工具类的一些步骤和最佳实践&#xff1a; ### 1. 创建工具类 首先&#xff0c;创建一个新的C类作为你的工具类。在Qt Creator中&#xff0c;可以通过右键点…...

vue3进阶用法之通过调用函数动态加载组件用法及示例

业务场景 假设现在有一个可能在全局任何地方调用的vue组件你会怎么办&#xff1f;非常简单&#xff0c;在app.vue下的router-view同级写上这个组件&#xff0c;在全局中加一个变量v-if判断这个变量就解决了&#xff01; tempalte中 <div><router-view /><You…...

线程和进程的关系

计算机是如何运行的&#xff1f;CPU 操作系统 进程管理 CPU 多核心 充分利用-> 并发编程&#xff0c;并发执行就算分时复用&#xff0c; 包括多进程编程。 多进程编程进程太重&#xff0c;创建进程&#xff0c;销毁进程开销比较大 &#xff0c;不利于频繁创建销毁进程&…...

《AI视频类工具之十二——​ EbSynth》

一.简介 官网:https://ebsynth.com/?ref=ai-bot.cn EbSynth是一款功能强大的视频风格转换工具,它利用先进的图像处理和计算机视觉技术,将静态艺术风格应用到视频中的每一帧,为视频创作者提供了全新的创作方式。 二.功能介绍 主要功能 视频转换:EbSynth 可以将视频转换…...

Facebook国内企业户、海外户、国内二不限户以及三不限户区别何在?

Facebook广告账户的类型和设置对于企业在不同市场中的广告活动至关重要。了解国内企业户、海外企业户&#xff0c;以及国内二不限户和三不限户的区别&#xff0c;可以帮助你更好地选择和管理广告账户。以下是对这些账户类型的详细解析。 一、Facebook海外企业广告账户 海外企业…...

修改 ASP.NET Core 应用程序运行后的默认端口

可以通过以下几种方法来实现。具体选择哪种方法取决于项目需求和环境设置。 方法 1&#xff1a;使用 appsettings.json 配置文件 你可以在 appsettings.json 中设置 Kestrel 的配置来更改默认端口。 打开 appsettings.json 文件&#xff0c;添加 Kestrel 配置&#xff1a; { …...

维基知识库系统Wiki.js本地Linux环境部署并配置公网地址远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

010集——按值传递、按引用传递等方法——C#学习笔记

按值传递参数 这是参数传递的默认方式。在这种方式下&#xff0c;当调用一个方法时&#xff0c;会为每个值参数创建一个新的存储位置。 实际参数的值会复制给形参&#xff0c;实参和形参使用的是两个不同内存中的值。所以&#xff0c;当形参的值发生改变时&#xff0c;不会影…...

Linux系统调优技巧

Linux系统调优技巧 Linux 性能调优技巧的深度分析及场景案例目录 1. Linux 性能调优的基础概念1.1 性能调优的目标1.2 常见的性能瓶颈 2. 系统监控与性能分析工具2.1 常用工具介绍2.2 实战案例&#xff1a;如何通过工具定位性能问题 3. CPU 性能调优3.1 CPU 负载分析3.2 CPU 调…...

计算机学习

不要只盯着计算机语言学习&#xff0c;你现在已经学习了C语言和Java&#xff0c;暑假又规划学习Python&#xff0c;最后你掌握的就是计算机语言包而已。 2. 建议你找一门想要深挖的语言&#xff0c;沿着这个方向继续往后学习知识就行。计算机语言是学不完的&#xff0c;而未来就…...

数字医学影像系统PACS源码,三甲以下医院都能满足,C#语言开发,C/S架构系统成熟稳定,支持二次开发项目使用。

数字医学影像系统&#xff08;RIS/PACS&#xff09;源码&#xff0c;三甲以下的医院都能满足。开发技术&#xff1a;C/S架构&#xff0c;C#开发语言&#xff0c;数据库服务器采用Oracle数据库。 PACS系统模块组成 &#xff1a; 工作站&#xff1a; 分诊工作站、超声工作站、放…...

C++语言基础|循环结构

C语言基础|循环结构 循环1. for语句2. while循环3. do…while语句 循环 在程序中&#xff0c;常常需要重复地执行某些操作。C提供了3种循环语句&#xff1a;for语句、while语句和do-while语句。在循环语句中&#xff0c;重复执行的操作叫做循环体。循环体可以是单条语句、块语…...

【学习笔记】解决在声音输出中找不到蓝牙耳机设备的问题

【学习笔记】在声音输出中找不到蓝牙耳机设备 在使用蓝牙耳机的时候&#xff0c;遇见一个问题&#xff0c;就是在电脑在连接蓝牙耳机之后&#xff0c;在声音输出中找不到蓝牙耳机设备&#xff0c;只能使用扬声器播放声音。电脑使用的是Windows 11系统。后来在网上寻找解决方案…...

PPPoE基础笔记

一、拨号原理 1.Discovery&#xff08;发现阶段&#xff09; PADI Client 发送广播的PADI报文&#xff0c;报文中包含Client想要的服务信息。 PADO Server收到PADI后&#xff0c;会向Client回复一个单播的PADO报文。 PADR Client 收到最先收到的PADO…...

开发组日志记录SPEC_v0.1.0

文章目录 开发组日志记录SPEC_v0.1.0目的设计逻辑1. User日志记录器1.1 记录器标签内容介绍1.2 程序打印User日志规则 2. Dev日志记录器2.1 记录器标签内容介绍2.2 程序打印Dev日志规则 3.代码说明3.1 代码详情3.2 使用说明 更新记录 时间版本内容修订者备注2024/08/150.1.0创…...

MySQL8 innoDB引擎的精髓

[client] port 3306 socket /var/lib/mysql/mysql.sock [mysql] #prompt"\umysqldb \R:\m:\s [\d]> " #关闭自动补全sql命令功能 no-auto-rehash ########################################################################### ##服务端参数配置 ######…...

【C语言实现花屏效果并打包程序为exe可执行文件】

说明&#xff1a;该程序为临摹改良(&#x1f600;)作品&#xff0c;源地址C/C屏幕恶搞程序 效果展示 上代码 #include <windows.h>#define NUM 11451LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int main() // Renamed WinMain to main {static int iKeep[NU…...

数据结构——排序(2):选择排序+交换排序

目录 一、选择排序 &#xff08;1&#xff09;直接选择排序 ①思路 ②过程图示 ③代码实现 ④代码解释 ⑤优化 1.代码实现 2.过程图示 3.代码解释 4.注意 ⑥直接选择排序的复杂度 &#xff08;2&#xff09;堆排序 ①注意 ②代码实现 二、交换排序 &#xff08…...

Next.js全栈开发模板:PostgreSQL+NextAuth+Tailwind一站式解决方案

1. 项目概述&#xff1a;一个现代化的全栈开发起点如果你最近在寻找一个能快速启动全栈Web应用开发的模板&#xff0c;那么由Vercel官方维护的这个“Next.js Postgres NextAuth Tailwind CSS”模板&#xff0c;很可能就是你一直在找的那个“瑞士军刀”。这不仅仅是一个简单的…...

openclaw-nerve:构建自包含应用包,彻底解决跨平台部署难题

1. 项目概述与核心价值最近在折腾一些自动化脚本和工具链&#xff0c;发现很多开源项目在依赖管理、环境配置和跨平台部署上&#xff0c;依然存在不小的摩擦。一个典型的场景是&#xff1a;你从GitHub上clone了一个看起来很酷的项目&#xff0c;满心欢喜地准备跑起来看看效果&a…...

3分钟掌握Windows文件占用检测:PowerToys File Locksmith终极解决方案

3分钟掌握Windows文件占用检测&#xff1a;PowerToys File Locksmith终极解决方案 【免费下载链接】PowerToys Microsoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows 项目地址: https://gitcode.com/GitHub_Trendi…...

别再手动画图了!用Python ASE + Matplotlib一键生成高质量材料结构图(附完整代码)

科研绘图革命&#xff1a;用Python ASEMatplotlib实现材料结构可视化自动化 深夜的实验室里&#xff0c;屏幕荧光映照着一张疲惫的脸——这可能是许多材料科学研究者共同的记忆。当你在论文截稿日前夕&#xff0c;还在反复调整VESTA中的原子位置、尝试各种角度截图时&#xff0…...

电信运营商M2M战略转型:从连接人到连接物的物联网新增长引擎

1. 从“人联网”到“物联金矿”&#xff1a;电信运营商的M2M战略转型 在过去的二十年里&#xff0c;全球的移动通信网络经历了一场狂飙突进&#xff0c;其核心使命始终围绕着“连接人”。从2G时代的短信和语音&#xff0c;到3G/4G时代的移动互联网&#xff0c;再到如今5G所描绘…...

氢燃料电池混合动力能量管理与动力控制【附仿真】

✨ 长期致力于氢燃料电池、能量管理、等效氢耗、变换器、协同控制、永磁同步电机、滑模自抗扰研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;等效氢耗…...

别再只会用ActivePart了!CATIA二次开发中,如何用C#递归遍历任意复杂结构树?

CATIA二次开发进阶&#xff1a;用C#递归算法征服任意复杂装配树 在CATIA二次开发领域&#xff0c;ActivePart就像新手司机的自动挡——简单易用却限制重重。当面对包含数百个零件的飞机发动机装配体&#xff0c;或是横跨多个产品的汽车底盘系统时&#xff0c;仅能操作当前激活零…...

TCRT5000循迹小车总跑偏?一份给STM32新手的硬件调试与软件滤波避坑指南

TCRT5000循迹小车调试实战&#xff1a;从硬件校准到软件滤波的完整解决方案 当你的STM32循迹小车在赛道上左右摇摆、频繁跑偏时&#xff0c;问题往往不只是代码逻辑那么简单。作为嵌入式开发新手&#xff0c;你可能已经尝试过调整PID参数、修改转向算法&#xff0c;但效果依然不…...

ArcGIS标注进阶:手把手教你搞定分式标注和河流左斜体(附完整表达式)

ArcGIS标注进阶&#xff1a;分式标注与河流左斜体实战指南 在地图制图领域&#xff0c;专业标注是提升可视化效果的关键环节。许多GIS工程师在进行水文地质制图时&#xff0c;常遇到分式标注格式混乱、河流名称无法实现标准左斜体等痛点问题。本文将彻底解决这些标注难题&#…...

JD-GUI深度解析:Java字节码逆向工程的瑞士军刀

JD-GUI深度解析&#xff1a;Java字节码逆向工程的瑞士军刀 【免费下载链接】jd-gui A standalone Java Decompiler GUI 项目地址: https://gitcode.com/gh_mirrors/jd/jd-gui 在Java开发的世界里&#xff0c;我们常常需要面对只有字节码没有源码的困境——第三方库的调试…...