C++面试速通宝典——9
170. 简述数组和指针的区别?
答:数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。
1. 修改内容上的区别
char a[] = “hello”;
a[0] = ‘X’;
char * p = “world”; //注意 p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
2. 用运算符sizeof可以计算出数组的容量(字节数)。sizeof§,p是指针,得到的是一个指针变量的字节数,而不是p所指的内存容量。
解释:
数组和指针是C/C++编程中的两个非常重要的概念,尽管它们有很多相似之处,但它们本质上是不同的东西。以下是数组和指针的一些主要区别:
数组和指针的定义
数组(Array)
- 数组是一个具有相同数据类型的元素的有序集合。在内存中,数组元素是连续存储的。
- 数组的大小在声明时是固定的,不能在运行时动态改变。
指针(Pointer)
- 指针是一个变量,用于存储另一个变量的内存地址。
- 指针可以指向不同类型的数据,并且可以在运行时改变指向的地址。
区别点
1. 内存分配
- 数组: 在编译时分配,大小固定。例如
int arr[5];分配5个 int 类型的连续内存空间。 - 指针: 可以在运行时分配,大小可以动态变化。例如
int *ptr = (int*)malloc(5 * sizeof(int));分配5个 int 类型的连续内存空间。
2. 声明和初始化
- 数组: 声明数组会自动分配指定大小的内存。例如
int arr[5]; - 指针: 必须手动指定分配内存,初始化时通常需要一个已有的地址,例如
int *ptr = NULL;或int *ptr = (int*)malloc(5 * sizeof(int));
3. 访问方式
- 数组: 可以使用数组下标直接访问元素,例如
arr[2]。 - 指针: 可以使用指针算术操作和解引用访问元素,例如
*(ptr + 2)或者ptr[2]。
4. 类型信息
- 数组: 类型包含了数组的大小。例如
int arr[5];是包含 5 个 int 类型元素的数组。 - 指针: 类型只包含指向的数据类型,不包含大小信息。例如
int *ptr是指向 int 类型数据的指针,但不包含指向多少个 int 元素的信息。
5. 存储方式
- 数组: 数组名代表数组的地址,但类型上也包含了数组长度的信息(仅在声明时)。
- 指针: 指针变量独立存在,可以指向不同的数据地址,不包含长度信息。
示例代码
#include <stdio.h>
#include <stdlib.h>int main() {// 数组示例int arr[5] = {1, 2, 3, 4, 5};printf("数组的第二个元素: %d\n", arr[1]);// 指针示例int *ptr;ptr = (int*)malloc(5 * sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return -1;}// 分配值for (int i = 0; i < 5; i++) {ptr[i] = i + 1; // 等同于 *(ptr + i) = i + 1;}printf("指针的第二个元素: %d\n", ptr[1]);// 释放内存free(ptr);return 0;
}
总结
- 数组是具有固定大小的连续内存块,声明时自动分配和初始化,可以用下标直接访问。
- 指针是一个变量,存储其他变量的地址,可以动态分配和修改内存地址,通过指针算术和解引用来访问数据。
171. C++函数中值的传递方式
值传递、指针传递、引用传递。
解释:
在C++中,函数参数的传递方式主要有三种:值传递(Pass by Value)、指针传递(Pass by Pointer)和引用传递(Pass by Reference)。每种传递方式都有其各自的特点和适用场景。下面逐一进行介绍:
1. 值传递(Pass by Value)
特点:
- 当函数参数使用值传递时,会在调用函数时将实际参数的值拷贝一份传递给函数。函数内部对参数的任何修改都不会影响到原变量。
- 主要用于传递简单的数据类型,如基本数据类型(int、char、float等)。
示例代码:
#include <iostream>void increment(int value) {value++;std::cout << "Inside function: " << value << std::endl;
}int main() {int num = 10;increment(num);std::cout << "Outside function: " << num << std::endl;return 0;
}
输出:
Inside function: 11
Outside function: 10
在这个例子中,increment函数接收到的是num的一个拷贝,因此对value的修改不会影响到num本身。
2. 指针传递(Pass by Pointer)
特点:
- 当函数参数使用指针传递时,传递的是实际参数的地址。函数内部通过指针可以直接访问和修改实际参数的值。
- 适用于需要在函数内部修改参数值的情况。
示例代码:
#include <iostream>void increment(int *value) {(*value)++;std::cout << "Inside function: " << *value << std::endl;
}int main() {int num = 10;increment(&num);std::cout << "Outside function: " << num << std::endl;return 0;
}
输出:
Inside function: 11
Outside function: 11
在这个例子中,increment函数接收到的是num的地址,因此通过解引用指针*value可以直接修改num的值。
3. 引用传递(Pass by Reference)
特点:
- 当函数参数使用引用传递时,传递的是实际参数的引用(别名)。函数内部对参数的任何修改都会直接影响到原变量。
- 比指针传递更安全,语法上也更简洁。
- 使用引用传递的参数在函数体内像普通变量一样使用,但实际上是对原始数据的引用。
示例代码:
#include <iostream>void increment(int &value) {value++;std::cout << "Inside function: " << value << std::endl;
}int main() {int num = 10;increment(num);std::cout << "Outside function: " << num << std::endl;return 0;
}
输出:
Inside function: 11
Outside function: 11
在这个例子中,increment函数直接接收到num的引用,因此对value的任何修改都会反映到num上。
总结
- 值传递: 函数接收到的是实际参数的一份拷贝,函数内部对参数的修改不会影响原变量。
- 指针传递: 函数接收到的是实际参数的地址,函数内部可以通过指针直接修改原变量的值。
- 引用传递: 函数接收到的是实际参数的引用,函数内部对参数的修改会直接影响原变量,用法上更简单且安全。
这三种传递方式各有优劣,选择哪种方式取决于具体的应用场景和需求。如果需要在函数中修改实际参数的值,推荐使用指针传递或引用传递;而对于传递大对象时,引用传递通常比值传递和指针传递更高效。
172. 内存的分配方式有哪几种?
答:有三种。
- 静态存储区:是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。
- 栈上分配:函数内的局部变量就是从这分配的,但分配的内存容量有限。
- 堆上分配:也称动态分配,如我们使用new、malloc分配内存,用delete、free来释放内存。
解释:
在讨论内存分配方式时,通常提到的三种方式(静态存储区、栈上分配和堆上分配)主要是指程序在运行时分配和管理内存的机制,而代码区的内存分配则是在程序加载时已经确定的,并且不在程序运行时动态分配或释放。因此,代码区的分配方式一般不包含在这三种运行时内存分配方式的讨论中。具体原因如下:
-
静态存储区:静态存储区分配的是全局变量和静态变量的内存,这些变量在程序加载时分配,并在程序整个运行期间保持不变。静态存储区的分配和代码区一样,是在程序加载时确定的,但它主要用于存储数据,而不是代码。
-
栈上分配:栈上分配用于存储函数的局部变量和函数调用的上下文信息(如返回地址、参数等)。栈上的内存分配是动态的,在函数调用时分配,函数返回时释放。这是一种运行时的内存管理机制。
-
堆上分配:堆上分配用于动态分配内存,例如通过
malloc、new等函数分配的内存。堆上的内存分配和释放是由程序员在运行时显式管理的,适用于需要动态管理生命周期的对象。
代码区的分配:代码区的内存分配是由操作系统在程序加载时完成的,并且是只读的。在程序运行期间,代码区的内容不会改变,也不会像栈或堆那样动态分配或释放内存。因此,代码区的分配属于程序加载时的静态分配,与运行时的内存分配机制有所不同。
综上所述,代码区的内存分配是在程序加载时完成的静态分配,与运行时的内存分配方式有所区别,因此通常不在讨论运行时内存分配方式时被提及。
代码区的分配是在程序编译和链接的过程中完成的。具体来说,代码区(又称文本区)存储的是程序的可执行指令,这些指令在程序运行时是只读的。代码区的分配过程可以概括为以下几个步骤:
-
编译阶段:在源代码编译时,编译器将源代码翻译成机器代码,并生成目标文件(通常是.o或.obj文件)。这些目标文件中包含了程序的机器指令和一些元数据。
-
链接阶段:链接器将一个或多个目标文件与库文件链接,生成最终的可执行文件。在这个过程中,链接器将所有目标文件中的代码段合并,并安排它们在最终可执行文件中的位置。
-
加载阶段:当程序被加载到内存中运行时,操作系统的加载器将可执行文件中的代码段加载到内存中的一个专门区域,这个区域就是代码区。加载器负责将代码段映射到内存中的一个只读区域,以确保代码在运行时不会被修改。
总结起来,代码区的分配是在编译和链接过程中由编译器和链接器完成的,最终在程序加载到内存时由操作系统的加载器负责实际的内存分配和映射。
173. extern"C"有什么作用?
答:
Extern"C"是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extern"C"后,C++就能直接调用C函数了。
Extern"C"主要使用正规DLL函数的引用和导出,在C++包含C函数或头文件的时候使用。使用时在前面加上extern "C"关键字即可。可以用一句话概括extern"C"这个声明的真实目的:实现C++与C以及其它语言的混合编程。
174. 用什么函数开启新线程、进程?
答:
新线程:CreateThread / AfxBegin Thread 等。
新进程:CreateProcess 等。
175. SendMessage 和 PostMessage 有什么区别?
答:
SendMessage是阻塞的,等消息被处理后,代码才能走到SendMessage的下一行。
PostMessage是非阻塞的,不管消息是否已经被处理,代码马上走到PostMessage下一行。
解释:
这段话描述了SendMessage和PostMessage在消息处理机制中的不同行为,特别是在Windows编程中。这两者都是用来将消息发送到指定的窗口或线程,但它们在执行时的行为有所不同。
SendMessage
SendMessage函数是同步的(阻塞的),这意味着它会将消息发送到目标窗口,并等待该消息被处理完毕之后,才返回并继续执行下一行代码。具体来说:
SendMessage将消息发送到目标窗口的消息队列。- 目标窗口的窗口过程(Window Procedure)接收并处理该消息。
- 处理完消息之后,
SendMessage返回结果。 - 代码继续执行
SendMessage之后的代码行。
因为SendMessage会等待消息被处理完毕,所以它是阻塞的。这意味着如果消息处理需要很长时间,调用SendMessage的线程会被阻塞,直到消息处理完成。
PostMessage
PostMessage函数是异步的(非阻塞的),这意味着它将消息放入目标窗口的消息队列后,立即返回并继续执行下一行代码,而不等待消息被处理。具体来说:
PostMessage将消息放入目标窗口的消息队列。PostMessage立即返回,不等待消息处理结果。- 代码继续执行
PostMessage之后的代码行。 - 目标窗口的消息队列会在合适的时间调度并处理该消息。
因为PostMessage不等待消息被处理,所以它是非阻塞的。这意味着调用PostMessage的线程可以继续执行,而不会因为消息处理的时间而被阻塞。
理解的关键点
- 阻塞和非阻塞:
SendMessage是阻塞的,调用线程必须等待消息被处理完才会继续执行。PostMessage是非阻塞的,调用线程无需等待消息处理结果,可以立即继续执行。 - 消息处理机制:
SendMessage要求同步处理消息,适合需要立即获得处理结果的场景。PostMessage则是异步处理消息,适合不需要立即获得处理结果,或者希望减少线程等待时间的场景。
示例代码
下面是一个简化的示例代码,展示了SendMessage和PostMessage的不同行为:
// SendMessage 示例
SendMessage(hWnd, WM_COMMAND, wParam, lParam);
// 只有在消息处理完成后,才会执行下一行代码
printf("SendMessage 后的代码");// PostMessage 示例
PostMessage(hWnd, WM_COMMAND, wParam, lParam);
// 立即返回并执行下一行代码,而不等待消息处理
printf("PostMessage 后的代码");
在SendMessage的情况下,只有当消息被处理完毕,才会打印"SendMessage 后的代码";而在PostMessage的情况下,消息一发送就立即打印"PostMessage 后的代码",不管消息是否被处理。
176. CMemoryState 的主要功能是什么?
CMemoryState查看内存使用情况,解决内存泄露的问题。
解释:
CMemoryState 是 MFC(Microsoft Foundation Class)库中的一个类,用于内存调试。它主要用于检测和报告内存泄漏。在调试版本的应用程序中,CMemoryState 可以保存内存的当前状态,并在需要时与另一状态进行比较,以检测内存的分配和释放情况是否一致。
CMemoryState 的主要功能
- 保存内存状态:
- 使用
CMemoryState::Checkpoint方法保存当前的内存状态。 - 通过保存多个内存状态,可以在不同的时间点记录内存使用情况。
- 使用
- 比较内存状态:
- 使用
CMemoryState::Difference方法比较两个内存状态。 - 可以检测出两个检查点之间的内存泄漏情况。
- 使用
- 报告内存泄漏:
- 使用
CMemoryState::DumpStatistics方法报告内存状态,包括内存泄漏信息。 - 可以输出内存泄漏的详细信息,帮助开发者定位和修复内存泄漏。
- 使用
代码示例
以下是一个使用 CMemoryState 检测内存泄漏的简单示例:
#include <afx.h>
#include <iostream>void TestMemoryLeak()
{// 创建一个内存块用于测试char* pMemory = new char[100];// 注意,这里故意没有删除内存,以测试内存泄漏
}int main()
{// 检查点1:在调用函数之前保存内存状态CMemoryState oldState, newState, diffState;oldState.Checkpoint();// 调用可能产生内存泄漏的函数TestMemoryLeak();// 检查点2:在调用函数之后保存内存状态newState.Checkpoint();// 比较两个检查点之间的内存状态if (diffState.Difference(oldState, newState)){std::cout << "Memory leaks detected:" << std::endl;diffState.DumpStatistics();}else{std::cout << "No memory leaks detected." << std::endl;}return 0;
}
代码解释
- 初始化内存状态:
CMemoryState oldState, newState, diffState;创建三个CMemoryState对象,用于保存不同时间点的内存状态。
- 保存内存状态:
oldState.Checkpoint();在调用TestMemoryLeak之前保存当前的内存状态。newState.Checkpoint();在调用TestMemoryLeak之后保存当前的内存状态。
- 比较内存状态:
diffState.Difference(oldState, newState);比较两个检查点之间的内存状态。- 如果检测到内存泄漏,
Difference方法将返回TRUE,并且diffState将包含泄漏的详细信息。
- 报告内存泄漏:
diffState.DumpStatistics();输出内存泄漏的详细信息。
通过这种方式,CMemoryState 可以帮助开发者在调试阶段检测和修复内存泄漏,确保应用程序的内存管理更加健壮和高效。
相关文章:
C++面试速通宝典——9
170. 简述数组和指针的区别? 答:数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。 1. 修改内容上的区别 char a[] “hello”; a[0] ‘X’; char * p …...
阿里巴巴商品详情API返回值:电商行业发展的新动力
阿里巴巴的商品详情API在电商行业中扮演着至关重要的角色,它不仅为商家和消费者提供了丰富的产品信息,还推动了电商行业的进一步发展和创新。通过API接口,开发者可以获取商品的详细信息,如标题、价格、库存、评价等,进…...
php的urlencode和rawurlencode区别
urlencode和rawurlencode都是用于对URL进行编码的函数,但它们在处理方式和应用场景上存在明显的区别。以下是关于这两个函数的详细比较: 一、定义与标准 urlencode:基于rawurlencode标准,但有略微的不同,它定义在rfc…...
LeetCode讲解篇之322. 零钱兑换
文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们可以使用动态规划解决这道题,我们首先定义一个数组,数组中第i个元素表示组成金额 i 的最少硬币个数 我们遍历数组的1 ~ amount号位置,对coins进行遍历,查找选…...
猴子吃桃-C语言
1.问题: 猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。 第二天早上又将剩下的桃子吃掉一半,又多吃一个。以后每天早上都吃了前一天剩下的一半零一个。 到第N天早上想再吃时,见只剩下一个…...
【C++】单例模式「详尽版」
欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 什么是单例模式如何实现单例模式饿汉模式和懒汉模式饿汉模式懒汉模式饿汉模式和懒汉模式的优缺点1.饿汉模式的优缺点2.懒汉模式的优缺点 什么是单例模式 C单例模式是一种非常重要的设计模式…...
MongoDB集群模式详解及应用实战
目录 本节课内容: 集群搭建 1.创建3个目录: 2.编辑配置文件 编辑 3.启动: 4.看看: 5.另外,两个如上1,2,3步骤操作 ,但是日志目录,端口什么的需要改一下即可。 …...
接着上一篇stp 实验继续
理论看上一篇,我们直接实验 首先找出root 桥 很明显 sw1 为root 桥,所谓sw1 &a…...
怎么将手机备忘录传送至电脑
在数字化时代,手机备忘录已成为我们生活中不可或缺的一部分。无论是记录购物清单、工作事项,还是灵感闪现的瞬间,手机备忘录都能随时记录下这些宝贵的信息,帮助我们防止遗忘。然而,有时候我们需要将这些备忘录内容转移…...
解决触摸屏屏幕乱动的问题:E: 无法定位软件包 libinput
在 Ubuntu 中,你可能已经有 libinput 库,它通常默认包含在系统中。如果你想使用 libinput 来管理输入设备(例如触摸屏或触摸板),通常不需要安装额外的软件包,而是直接使用系统自带的工具。 不过࿰…...
RISC-V笔记——基础
1. 前言 RISC-V旨在支持广泛的定制和专业化。RISC-V的ISA是由一个基本整型ISA和其它对基本ISA的可选扩展组成。每个整型ISA可以使用一个或多个可选的ISA扩展进行扩展。 基本整型ISA精选了最小的一组指令,这些指令足以为编译器、汇编器、链接器和操作系统提供足够的…...
「Kafka」Kafka消息可靠性和重复消费问题(五)
在 Kafka 中,实现消息的可靠性和避免重复消费是保证数据一致性和系统稳定性的关键。Kafka 提供了多种机制来实现这两个目标。 1. Kafka 消息可靠性 Kafka 的可靠性主要体现在消息的投递和存储上,以确保消息不会丢失。具体来说,有以下几个措…...
现代身份和访问管理 IAM 如何降低风险
您的公司是否仍在使用 1998 年时的身份管理系统?仅凭用户名和密码就能登录本地网络并访问几乎所有资源吗? 虽然大多数企业已经转向现代身份和访问管理(IAM) 平台,但成千上万的企业和其他组织仍然依赖过时的用户名/密码系统。 如果你看一下传…...
2024年江西省职业院校技能大赛(高职组)信息安全管理与评估”赛项竞赛规程
附件 1 2024年江西省职业院校技能大赛(高职组)信息安全管理与评估”赛项竞赛规程附件 1 一、赛项名称 信息安全管理与评估赛 二、竞赛目的 通过赛项检验参赛选手网络组建、按照等保要求加固网络、安全架构、 渗透测试等技术能力,检验参赛队计划组织和团队协作等综合…...
在 Koa 中,中间件函数的参数ctx是什么?
在 Koa 中,ctx 是指 context 对象,它是请求与响应的上下文,封装了 request 和 response。每当 Koa 收到一个 HTTP 请求时,都会为该请求创建一个 ctx 对象,ctx 使开发者可以通过它方便地获取请求信息并设置响应。 ctx …...
在 Gitlab 中使用 ChatGPT 进行 CodeReview
ChatGPT集成Gitlab,实现自动代码审计并进行评论,为软件开发团队提供高效、智能的代码审查解决方案。支持其他模型如通义千问等 自动触发与及时响应:利用Gitlab的Webhook功能,实现代码提交、合并请求和标签创建等事件的自动触发。一…...
解决新版Android studio不能连接手机的问题
我要说的是一个特例,装了22年的版本AS可以正常连接手机,装了23年以后新版本,AS不能正常连接手机了,但是在CMD控制台可以正常的执行adb命令,并且CMD和AS都是指向D:\android_sdk\platform-tools\adb.exe 一、 为什么会出…...
arcgis for js点位渲染与实际坐标不一致且popupTemplate偏移
问题描述 arcgis for js 鼠标点击地图时的经纬度, 使用该经纬度加载一个Point点, 该Point点渲染位置与实际经纬度不一致(存在偏差)该Point点设置popupTemplate弹窗, 点击Point点无法弹出 (位置偏移导致) 原因 地图容器或更外层元素CSS的scale属性导致...
定点数和浮点数的详细介绍(一)定义、范围、位宽
1.定点数 1.1定点数描述 定点数包括定点小数(纯小数)、定点整数(纯整数)、整数和小数位数固定的实数。 1.2定点小数: 小数点默认在符号位后面,首位为符号位,其他为数值位(在用二进制代表小数时,例如0xFF,就表示0.5+0.25+0.125+0.0625+0.03125........) 例如,用…...
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
集群环境搭建 在 Redis 5版本以前是用 Ruby 来搭建集群,在后面的版本中仍保留了相关功能可以再源码src目录中,看到 redis-trib.rb 这个东西,只是现在用这种方式搭建的少了我们看新的版本是怎样搭建集群的,新版构建集群的方式简单…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
