自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(49)
  • 收藏
  • 关注

原创 STM32G030C8T6 串口外部中断读取ADC值打印五向按键方向

本实验通过配置STM32G030C8T6的PA8引脚为外部中断,并在中断处理函数中读取ADC值,成功实现了五向按键的方向检测,并通过串口助手打印方向信息。实验现象与预期一致,验证了实验的可行性和正确性。通过配置PA8为外部中断引脚,当五向按键被按下时,PA8会产生上升沿触发中断。在中断处理函数中,读取PA1的ADC值,根据不同的ADC值判断按键的方向,并通过串口将方向信息打印出来。

2024-06-28 22:36:37 850

原创 STM32G030LED闪烁以及流水灯实验文档

控制一个LED灯(D7黄灯)在固定时间间隔内闪烁。

2024-06-27 23:27:12 571

原创 STM32G030C8TX UART中断实验文档

每发送10次数据(如"hh"),STM32都会触发接收中断,将接收数据存储在缓冲区中,并通过回调函数发送“rx end \r\n”消息,再将缓冲区数据发送回串口助手,并发送“tx end \r\n”消息。在本实验中,利用UART中断机制,当接收到数据或数据传输完成时触发中断,并执行相应的回调函数处理数据。通过本次实验,我们了解了如何配置STM32G030C8TX的UART中断,如何利用接收和发送完成回调函数处理数据,实现UART通信。

2024-06-27 20:30:48 747

原创 嵌入式系统中的中断

中断是一种重要的机制,用于嵌入式系统中处理各种突发事件。中断允许处理器暂时中止当前执行的任务,去处理更紧急的事件,然后再回到之前的任务继续执行。这种机制极大地提高了系统的响应能力和效率。

2024-06-27 15:19:50 847

原创 Person类与Employee 类的多态实现

有一个基类Person类,包含了私有成员姓名和职业。有若干派生类Employee类,继承了该类。要求用虚函数实现Person类的多态性。本示例演示了如何使用基类(Person)与派生类(Employee)来实现多态性。Person类包含了人的基本信息,如姓名和职业,而Employee类则继承了Person类,并增加了员工ID的属性。通过使用虚函数(printInfo)和虚析构函数,我们实现了多态性,并确保了派生类对象的正确析构。

2024-06-05 19:10:40 242

原创 C++ 智能指针(修订版)

智能指针是C++标准库提供的一种用于自动化内存管理的工具。它通过RAII(Resource Acquisition Is Initialization)机制,确保在对象生命周期结束时自动释放资源,避免内存泄漏和悬空指针等问题。

2024-06-05 19:08:54 318

原创 C++拷贝构造函数和移动构造函数(修订版)

拷贝构造函数是用来创建一个对象,该对象是使用另一个同类型的对象初始化的。移动构造函数用于通过“移动”资源来构造一个新的对象,而不是复制。在C++中,拷贝构造函数和移动构造函数是对象管理的重要部分。理解并正确使用它们可以显著提升程序的性能和可靠性。希望通过本教程,你能够更好地掌握这两个构造函数的使用技巧。

2024-06-05 19:07:53 386

原创 C++继承与构造函数

当基类和派生类存在同名成员时,可以通过类名来进行区分。可以通过类名来区分它们,例如在主函数中使用。

2024-06-05 19:06:47 681

原创 C++构造函数和拷贝构造函数

这行代码在标准C++中是有效的,但由于它涉及到一个内部的临时对象,它实际上会触发拷贝初始化。然而,由于拷贝构造函数通常是私有的(在某些类中),该代码通常不会出现在实际的代码中,除非拷贝构造函数是公开的。然而,由于C++17之前的编译器优化(称为“拷贝省略”或“RVO”),在这种情况下可能不会实际调用拷贝构造函数,而是直接使用直接初始化的结果来构造。在C++中,构造函数和拷贝构造函数是两种特殊的成员函数,它们在对象的创建和初始化时起着至关重要的作用。是通过拷贝初始化来创建的,因此会调用拷贝构造函数。

2024-06-01 20:52:27 535

原创 C++友元函数和友元类

定义友元函数是一种非成员函数,但它可以访问类的私有(private)和保护(protected)成员。友元函数是通过在类定义中声明为friend来指定的。特点非成员函数:友元函数不是类的成员函数,因此它没有this指针。访问权限:友元函数可以访问类的私有和保护成员。声明位置:友元函数的声明可以在类的私有、保护或公有部分进行,但通常建议放在类的私有部分,以强调它不是类的正常接口。定义位置:友元函数的定义可以在类定义内部或外部进行。如果定义在类外部,则不需要使用类的作用域解析运算符(用途。

2024-06-01 16:31:34 330

原创 C++懒汉和饿汉单例设计模式

不过,在单线程环境中,或者你确定在多线程环境中不会有问题的情况下(例如,你控制了单例的访问,并确保它在任何时间点只被一个线程访问),这种简单的懒汉式单例是可以接受的。而在懒汉式中,由于对象的创建是延迟的,所以需要使用指针来表示对象可能尚未存在的情况。在饿汉式单例模式中,单例对象在程序开始时或在单例类首次被加载到内存中时就被创建,因此不存在线程安全问题,因为静态初始化在多线程环境中是安全的。在饿汉式单例模式中,单例对象的生命周期通常与程序的生命周期相同,因此,在大多数情况下,你并不需要显式地销毁它。

2024-06-01 10:22:32 712

原创 using namespace std是什么

是 C++ 编程语言中的一个指令,它用于告诉编译器在接下来的代码块中,可以直接使用std(标准)命名空间中的名称,而不需要每次都加上前缀。std是 C++ 标准库(Standard Library)的命名空间。标准库包含了一组非常有用的函数、对象、类、模板等,用于处理常见的编程任务,如输入/输出、字符串处理、容器类(如向量、列表、映射等)、算法等。例如,如果你没有使用,那么当你想要使用标准库中的cout对象来输出文本时,你需要写std::cout。但是,如果你已经写了,那么你就可以直接写cout了。

2024-05-30 19:53:24 314

原创 c语言中char 和char []

char *p和char[]在本质上都是对字符数组的引用,但它们在内存分配、生命周期和用法上有所不同。在函数传参时,两者都可以作为字符串的引用传递,但在返回值时需要特别注意内存管理和生命周期的问题。在使用strcpy时,需要确保目标空间有足够的内存来存储源字符串,并避免缓冲区溢出等安全问题。在C语言中,字符数组和字符指针都是用于处理字符串的重要概念,但它们之间存在一些关键的区别。字符串字面量(String Literal)在C语言和其他许多编程语言中是一个直接表示文本数据的常量。

2024-05-30 10:53:06 601

原创 现代编程语言关于函数(方法)按值传递和按引用传递

函数(Function)和方法(Method)在编程中经常被提及,虽然它们在很多情况下做的事情相似,但在不同的编程语言环境中,它们之间确实存在一些差异。

2024-05-30 10:49:04 628

原创 随机化快排

如果每次都选择最大或最小的元素作为枢轴,可能导致每一轮划分只能将数组分成一个较小的部分和一个较大的部分,从而使得排序的效率变低,时间复杂度接近于 O(n2)O(n^2)O(n2)。这样做的目的是为了减少最坏情况的出现概率,提高算法的性能稳定性。在每一轮划分中,选择一个合适的枢轴元素,然后将数组中比枢轴元素小的元素移动到枢轴元素的左边,比枢轴元素大的元素移动到右边,这样就将数组分成了两部分。因此,选择一个合适的枢轴元素是快速排序算法的关键,而随机化快排通过随机选择枢轴元素的方法,提高了算法的性能稳定性。

2024-05-29 19:21:55 265

原创 TCP服务端、客户端模型

Socket是网络通信中的一个重要概念,它提供了一种端对端的通信方式,使得不同主机上的应用程序可以相互通信。通过创建和使用 Socket,我们可以实现基于 TCP 或 UDP 的网络通信。在 TCP Socket 中,我们还需要了解三次握手、数据传输和四次挥手等基本概念和工作原理。流式套接字和数据报套接字的主要区别在于它们的可靠性和连接性。流式套接字(SOCK_STREAM)提供可靠的、面向连接的通信服务,而数据报套接字(SOCK_DGRAM)则提供不可靠的、无连接的通信服务。

2024-05-29 19:14:45 539

原创 高位和低位的概念

关于0x12345678在小端节序是先读78的解释:在小端字节序(Little-Endian)系统中,多字节数据的最低有效字节(Least Significant Byte, LSB)存储在最低的内存地址上,而最高有效字节(Most Significant Byte, MSB)则存储在较高的内存地址上。如果发送方和接收方使用了不同的字节序,那么在接收方收到数据后,通常需要将其从网络字节序(大端字节序)转换为主机字节序(可能是小端或大端),或者从主机字节序转换为网络字节序。,因为它是最低有效字节(LSB)。

2024-05-29 19:10:43 1690

原创 网络7层OSI

OSI(Open Systems Interconnection)七层模型是网络通信中的一个重要概念,它定义了网络通信中的各个层次及其功能。以上就是OSI七层模型通信的基本流程。需要注意的是,在实际的网络通信中,不同的层次之间会进行交互和协作,以确保数据的正确传输和处理。

2024-05-29 19:08:55 753

原创 五大内存区域

在 C 语言中,一般将内存分为五大区域:栈区(stack)、堆区(heap)、全局/静态区(global/static area)、常量区(constant area)和代码区(code/text area)。C 语言中的内存区域主要包括栈(stack)、堆(heap)、全局静态区(global/static area)和常量区(constant area)。这些内存区域在程序运行期间扮演不同的角色,了解它们的特性有助于编写安全、高效的 C 代码。通过打印这些变量的地址,你可以看到它们存储的位置。

2024-05-29 19:06:47 351

原创 生产者消费者线程用互斥锁

通常情况下,条件变量需要和互斥锁一起使用,以保护共享资源的访问。在等待条件变量之前,线程通常会先获取互斥锁,然后在条件不满足时等待条件变量,直到另一个线程通过释放互斥锁并发送信号来通知条件满足。条件变量提供了一种线程等待的机制,它允许一个线程等待另一个线程满足特定的条件,然后在条件满足时通知等待的线程继续执行。是 POSIX 线程库中定义的条件变量的数据类型,用于线程之间的同步和通信。来实现生产者和消费者之间的同步,确保在缓冲区满或者空的情况下,生产者和消费者线程能够正确地等待和唤醒。:等待条件变量满足。

2024-05-29 19:02:50 141

原创 Linux 系统中,把一切都看做是文件(一切皆文件)

Linux 系统中,把一切都看做是文件(一切皆文件),当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。文件描述符(File Descriptor)是一个用于表述指向被打开的文件引用的抽象化指标。在Unix、Linux和其他类Unix操作系统中,文件描述符是一个非负整数,用于指代被打开的文件。

2024-05-29 19:00:05 799

原创 程序、进程、线程、协程结构图

线程是进程的最小执行单元,一个进程可以包含多个线程,它们共享进程的地址空间和资源,是操作系统调度的基本单位。协程是轻量级的线程,是线程的最小执行单元,它在用户空间中实现,不依赖于操作系统的线程调度。协程之间可以自由切换,但不会被操作系统调度,而是由程序自身控制。这种区分可以帮助我们理解它们在并发编程中的不同作用和特点。

2024-05-29 18:57:52 572

原创 Linux中僵尸进程和孤儿进程概念

Linux中僵尸进程和孤儿进程概念僵尸进程(Zombie Process)僵尸进程是指已经结束执行但父进程尚未调用wait()或waitpid()来获取其终止状态的子进程。在进程表中仍然保留其进程号和退出状态。僵尸进程占用系统资源,但不再执行任何代码。僵尸进程等待父进程来获取其终止状态。孤儿进程(Orphan Process)孤儿进程是指父进程终止或者被终止,而子进程尚未被回收的进程。孤儿进程将被init进程(进程号为1)收养。init进程会负责回收孤儿进程,防止其成为僵尸进程。

2024-05-29 18:54:05 129

原创 分析多路IO复用的原理

多路I/O复用是现代网络编程中非常重要的技术,允许一个单独的线程或进程同时监视多个文件描述符(通常是套接字),从而能够在这些描述符之一准备好进行I/O操作时进行相应的处理。系统调用允许程序监视多个文件描述符,等待其中的一个或多个变为"就绪"状态(可读、可写或异常)。时,程序可以指定三个文件描述符集(可读、可写和异常),以及一个超时时间。调用后,程序会检查哪些文件描述符已就绪,并对其进行处理。的示例程序,演示了如何将监听文件描述符加入集合,并在。的简单案例,展示了它的基本使用方法。(在Linux上)。

2024-05-29 18:49:08 555

原创 分析进程、线程实现TCP服务端多任务的原理、步骤以及优缺点

选择进程还是线程实现 TCP 服务端多任务需要根据具体应用场景权衡。如果追求稳定性且系统资源充足,可以选择进程方式。如果对性能要求较高且能合理处理线程同步问题,可以选择线程方式。)创建线程来处理每个客户端连接。每当有新的客户端连接到来,服务器会创建一个新的线程,由该线程处理客户端的请求。在 Linux 中,实现 TCP 服务端多任务的方式主要有两种:通过进程(如。创建子进程来处理每个客户端连接。每当有新的客户端连接到来,服务器会调用。创建一个新的子进程,由子进程来处理该客户端的请求。

2024-05-29 18:47:36 578

原创 总结多路IO复用

多路IO复用是Linux系统中处理多个文件描述符(FD)的一种机制。它允许一个程序在单个线程中同时处理多个输入/输出事件,从而提高效率和性能。主要的多路IO复用机制包括select和epoll。

2024-05-29 18:45:21 326

原创 使用 select 实现的简单 TCP 服务器

这段代码展示了如何使用select系统调用管理多个客户端连接。服务器在每个连接上循环接收数据并处理客户端断开的情况。通过select,服务器能够同时处理多个连接,而不会阻塞在单个 I/O 操作上。

2024-05-29 18:43:13 708

原创 使用epoll管理多个客户端连接的TCP服务器

在这个示例中,我们将定义一个(无头)链表来管理在线客户端。链表节点将包含客户端的文件描述符和其他必要信息,如客户端的地址信息。我们还会编写相关的函数来管理这个链表,包括添加客户端、移除客户端和遍历客户端列表。// 链表节点结构int fd;// 添加新客户端到链表// 从链表中移除客户端if (temp!free(temp);return;// 遍历链表并打印客户端信息= NULL) {// 清理链表。

2024-05-29 18:41:36 666

原创 引用(reference)和指针(pointer)

这种能力使得引用成为一种非常强大的工具,但也需要小心使用,以避免生命周期问题(如返回局部变量的引用)和不必要的副作用。指针常量是指一个指针,它自身的地址是常量,即这个指针一旦被初始化,就不能再指向其他的地址。但是,你可以通过这个指针来修改它所指向的数据的值(如果该数据不是常量的话)。在C++中,引用(reference)和指针(pointer)都是用于间接访问和操作其他变量的机制,但它们之间存在一些重要的区别。是一个全局变量,它的生命周期与程序的生命周期相同,所以返回的引用是安全的。

2024-05-29 17:32:44 661

原创 scanf 和 printf ; sscanf 和 sprintf ; fscanf 和 fprintf 的区别

scanfprintfsscanfsprintffscanf和fprintf是 C 语言中用于输入和输出操作的标准库函数,它们之间有一些明显的区别,主要体现在它们处理输入/输出的源/目标上。

2024-05-27 21:16:05 558

原创 指针与函数参数

在 C 语言中,当一个指针作为参数传递给函数时,函数接收到的是该指针的拷贝,但指针指向的内存地址是相同的。因此,函数内部可以通过解引用该指针来修改指针指向的内存内容,这实际上是对函数外部变量的修改。传递结构体的指针给函数,并且在函数内部使用箭头运算符 -> 来访问和修改结构体的成员,那么任何对结构体成员的修改都会直接影响到原始结构体,因为指针指向的是原始结构体的地址。当你想要修改数组中的元素时,你可以传递数组的地址给函数,然后通过索引来访问和修改数组的元素。

2024-05-27 19:38:08 306

原创 scanf 和 printf ; sscanf 和 sprintf ; fscanf 和 fprintf 的区别

scanfprintfsscanfsprintffscanf和fprintf是 C 语言中用于输入和输出操作的标准库函数,它们之间有一些明显的区别,主要体现在它们处理输入/输出的源/目标上。

2024-05-27 15:22:13 1008

原创 动态库和静态库有什么区别?

静态库:编译时链接,代码被复制到可执行文件中,生成的可执行文件较大但独立,升级和维护需要重新编译。动态库:运行时加载,代码不被复制到可执行文件中,生成的可执行文件较小但有外部依赖,升级和维护方便。在开发过程中,选择使用静态库还是动态库取决于项目的具体需求和场景。例如,如果项目对执行文件的大小有严格限制,或者需要在没有库文件的机器上运行,那么可能会选择使用静态库。而如果项目需要多个程序共享库代码,或者需要方便地进行库代码的升级和维护,那么可能会选择使用动态库。

2024-05-23 20:05:20 542

原创 if (5==i)和if(i==5)的区别

然而,现代的编程环境和编译器通常会通过警告或错误来指出这种潜在的错误,所以Yoda条件的必要性已经大大降低。通常被认为是更自然和更直观的写法,因为它遵循了“先读变量名,再读常量”的习惯。但是,无论你选择哪种写法,都应该确保你的代码是清晰、可读和易于理解的。,这实际上是一个合法的赋值操作,并且其结果是5(在C和C++中,赋值操作的结果是被赋的值),这通常会导致。编译器会优化这种简单的比较操作,所以无论你选择哪种写法,都不会对程序的性能产生任何影响。遵循团队的规范是很重要的,以保持代码的一致性。

2024-05-23 19:58:05 184

原创 关于i++和++i 的区别

在循环条件中,++i(前置递增)和i++(后置递增),因为循环条件只关心递增后的值是否满足继续循环的条件。但是,它们在循环体内部的行为和语义上是不同的。和在上面的例子中,无论是使用++i还是i++i都会递增,并且循环会继续执行直到i不再小于 10。在循环条件的判断过程中,前置递增和后置递增产生的值(即递增后的i的值)是一样的,因此循环的行为没有区别。然而,如果你在循环体内部使用了递增操作,并且关心递增操作与其他操作的顺序,那么前置递增和后置递增就会有区别。但在循环条件本身中,++i和i++

2024-05-23 19:53:53 403

原创 数据结构之栈和队列

对于队列的操作,你有两个主要选项,但通常我们只考虑其中一种,即“在尾部添加(enqueue),在头部移除(dequeue)”。至于你提到的“在头部添加,在尾部移除”,这不是队列的典型操作,这样的数据结构通常被称为“双端队列”(Deque)或“双端链表”。例如,在函数调用时,计算机使用栈来存储局部变量和返回地址,这样当函数返回时,它可以恢复调用它的函数的状态。在这些应用中,元素按照它们到达的顺序进行处理,先到达的元素先被处理。:最后一个被“压入”(push)栈的元素总是第一个被“弹出”(pop)的元素。

2024-05-21 21:01:40 178

原创 无头链表增删改查和有头链表增删改查

这个版本的代码具有头节点,头节点用于简化对链表的操作,并且在遍历和操作链表时,不需要额外的空指针检查。

2024-05-21 21:01:00 168

原创 随机化快排

如果每次都选择最大或最小的元素作为枢轴,可能导致每一轮划分只能将数组分成一个较小的部分和一个较大的部分,从而使得排序的效率变低,时间复杂度接近于 O(n2)O(n^2)O(n2)。这样做的目的是为了减少最坏情况的出现概率,提高算法的性能稳定性。在每一轮划分中,选择一个合适的枢轴元素,然后将数组中比枢轴元素小的元素移动到枢轴元素的左边,比枢轴元素大的元素移动到右边,这样就将数组分成了两部分。因此,选择一个合适的枢轴元素是快速排序算法的关键,而随机化快排通过随机选择枢轴元素的方法,提高了算法的性能稳定性。

2024-05-21 21:00:20 243

原创 算法时间复杂度和空间复杂度

典型的例子包括只需要几个常量大小的变量来存储数据的算法,如常量大小的数组或固定数量的变量。通常是在算法执行过程中需要存储与输入大小成比例的数据结构,例如,存储输入数组的副本或创建与输入大小成比例的数据结构(例如,链表)。这意味着算法的性能不受输入规模的影响,常见于一些简单的操作,如访问数组中的元素、插入或删除链表的头部等。理解和分析算法的时间复杂度对于设计高效的算法和评估算法的性能至关重要。通常情况下,我们希望选择空间复杂度较低的算法,以节省内存并提高算法的效率。:算法的执行时间与输入规模的平方成正比。

2024-05-21 20:59:49 281

原创 三路快速排序

三路快速排序是一种改进的快速排序算法,旨在解决在含有大量重复元素的数组中性能下降的问题。它在原始的快速排序算法的基础上,将数组分为三部分,分别是小于、等于和大于基准元素的部分。这样,在含有大量重复元素的情况下,可以减少递归的深度,从而提高性能。指针将数组分为小于、等于和大于基准的三部分。然后递归地对小于和大于基准的两部分进行排序。在遍历数组时,通过不断地交换元素的位置,将数组分成三个部分,以实现三路快速排序的目的。函数中,首先选择数组的第一个元素作为基准,然后通过。这段代码实现了三路快速排序算法。

2024-05-21 20:59:19 177

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除