FreeRTOS队列
队列简介
队列是一种任务到任务,任务到中断,中断到任务数据交流得一种机制。在队列中可以存储数量有限,大小固定得多个数据,队列中的每一个数据叫做队列项目,队列能够存储队列项目的最大数量称为队列的长度,在创建队列的时候就需要指定所创建的队列的长度以及队列项目的大小。因为队列是用来在任务与任务或任务与中断之间传递消息的一种机制,因此队列也叫做消息队列。
数据存储
队列通常采用FIFO(先进先出)的存储缓冲机制,当有新的数据被写入队列中时,永远都是写入到队列的尾部,而从队列中读取数据时,永远都是读取队列的头部数据。但同时FreeRTOS的队列也支持将数据写入到队列的头部,并且可以指定是否覆盖先前已经在队列头部的数据(对应3种写入数据的方式)。
多任务访问
队列不属于某个特定的任务,可以在任何的任务或中断种往队列中写入消息,或者从队列中读取消息。
队列读取阻塞
在任务从队列读取消息时,可以指定一个阻塞超时时间。如果任务在读取队列时,队列为空,这时任务将被根据指定的阻塞超时时间添加到阻塞态任务列表中进行阻塞,以等待队列中有可用消息。当有其他任务或中断将消息写入队列中,因等待队列而阻塞任务将会被添加到就绪态任务列表中,并读取队列中可用的消息。如果任务因等待队列而阻塞超时时间超过指定的阻塞超时时间,那么任务也将自动被转移到就绪态任务列表中,但不再读取队列中的数据。
因为同一个队列可以被多个任务读取,因此可能会有多个任务因等待同一个队列,而被阻塞,在这种情况下,如果队列中有可用的消息,那么也只有一个任务会被解除阻塞并读取到消息,并且按照阻塞的先后和任务的优先级,决定应该解除哪一个队列读取阻塞任务。
队列写入阻塞
与队列读取一样,在任务往队列写消息时,也可以指定一个阻塞超时时间。如果任务在写入队列时,队列已经满了,这时任务将被根据指定的阻塞超时时间添加到阻塞态任务列表中进行阻塞,以等待队列有空闲的位置可以写入消息。指定的阻塞超时时间为任务阻塞的最大时间,如果在阻塞超时时间到达之前,队列有空闲的位置,那么队列写入阻塞任务将会解除阻塞,并往队列中写入消息,如果达到指定的阻塞超时时间,队列依旧没有空闲的位置写入消息,那么队列写入阻塞任务将会自动转移到就绪态任务列表上,但不会往队列中写入消息。
因为队列可以被多个任务写入,因此可能会有多个任务因等待同一个任务,而被阻塞,在这种情况下,如果队列中有空闲的位置,那么也只有一个任务会被解除阻塞态并往队列中写入消息,并且会按照阻塞的先后和任务的优先级,决定应该解除哪一个队列写入阻塞任务。
队列的特性
常规特性
队列的简化操作如下图所示,从图中可以知道:
队列可以包含若干个数据,队列中有若干项,这被称为“长度(length)”
每个数据大小固定
创建队列时就要指定长度,数据大小
数据的操作采用先进先出的方法(FIFO,First In First Out);写数据时放到尾部,读数据时从头部读
也可以强制写队列头部,覆盖头部数据

更详细的操作如下图所示:

传输数据的两种方法
使用队列传输数据时有两种方法:
拷贝:把数据、把变量的值复制进队列里
引用:把数据,把变量的地址复制进队列里
FreeRTOS传输小数据的时候,可以采用值传递,传输大数据时采用引用的方式
局部变量的值可以发送到队列里,后续即使函数退出,局部变量被回收,也不会影响队列中的数据
无需分配buffer来保存数据,队列中有buffer
局部变量马上可以再次使用
发送任务、接收任务解耦:接收任务不需要知道这数据是谁的、也不需要发送任务来释放数据
如果数据实在太大,你还是可以使用队列传输它的地址
队列的空间有FreeRTOS内核分配,无需任务操心
对于有内存保护功能的系统,如果队列使用引用方法,也就是使用地址,必须确保双方任务对这个地址都有访问权限。使用拷贝方法时,则无此限制:内核有足够的权限,把数据复制进队列、再把数据复制出队列。
队列的阻塞访问
只要知道队列的句柄,谁都可以读,写该队列。任务,ISR都可读,写队列。可以多个任务读写队列。
任务读写队列时,简单地说:如果读写不成功,则阻塞,可以指定超时时间。口语化的说,就是说可以定个闹钟;如果能读写了就马上进入就绪态,否则就阻塞到超时。
某个任务读队列时,如果队列没有数据,则该任务可以进入阻塞态;还可以指定阻塞时间。如果队列有数据了,则该阻塞的任务会变为就绪态。如果一直都没有数据,则时间到之后它也会进入就绪态。
既然读取 队列的任务个数没有限制,那么当多个任务读取空队列时,这些任务都会进入阻塞态,有多个任务在等待同一个队列的数据。当队列中有数据时,哪个任务会进入就绪态?
优先级最高的任务
如果大家优先级相同,那等待时间最久的任务会进入就绪态
跟读队列时类似,一个任务要写队列时,如果队列满了,该任务可以进入阻塞态;还可以指定阻塞的时间,如果队列有空间了,则该阻塞的任务就会变为就绪态。如果一直都没有空间,则时间到之后它会进入就绪态。
既然写队列的任务个数没有限制,那么当多个任务写“满队列”时,这些任务都会进入阻塞态,有多个任务在等待同一个队列的空间,当队列中有空间时,哪个任务会进入就绪态?
优先级最高的任务
如果大家优先级相同,那等待时间最久的任务会进入就绪态
队列结构体
typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{int8_t * pcHead; /*< 存储区域的起始地址 */int8_t * pcWriteTo; /*< 下一个写入的位置 */union{QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */} u;List_t xTasksWaitingToSend; /*< 等待发送列表 */List_t xTasksWaitingToReceive; /*< 等待接收列表 */volatile UBaseType_t uxMessagesWaiting; /*< 非空闲队列项目的数量/UBaseType_t uxLength; /*< 队列长度 */UBaseType_t uxItemSize; /*< 队列项目的大小 */volatile int8_t cRxLock; /*< 读取上锁计数器*/volatile int8_t cTxLock; /*< 写入上锁计数器 */#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */#endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition * pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif
} xQUEUE;/* The old xQUEUE name is maintained above then typedefed to the new Queue_t* name below to enable the use of older kernel aware debuggers. */
typedef xQUEUE Queue_t;

队列相关的API函数
使用队列的流程:创建队列,写队列,读队列、删除队列
创建
队列的创建有两种方法:动态内存分配,静态内存分配
动态内存分配:xQueueCreate,队列的内存在函数内部动态分配
函数原型如下:
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
参数 | 说明 |
uxQueueLength | 队列长度,最多能存放多少个数据(item) |
uxItemSize | 每个数据(item)的大小:以字节为单位 |
返回值 | 非0:成功,返回句柄,以后使用句柄来操作队列 NULL:失败,内存不足 |
静态内存分配:xQueueCreateStatic,队列的内存要实现分配好
函数原型如下:
QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorage,StaticQueue_t *pxQueueBuffer);
参数 | 说明 |
uxQueueLength | 队列长度,最多能存放多少个数据(item) |
uxItemSize | 每个数据(item)的大小:字节为单位 |
pucQueueStorag | 如果uxItemSize非0,pucQueueStorageBuffer必须指向一个uint8_t数组, 此数组大小至少为"uxQueueLength * uxItemSize" |
pxQueueBuffer | 必须执行一个StaticQueue_t结构体,用来保存队列的数据结构 |
返回值 | 非0:成功,返回句柄,以后使用句柄来操作队列 NULL:失败,因为pxQueueBuffer为NULL |
示例代码:
// 示例代码#define QUEUE_LENGTH 10#define ITEM_SIZE sizeof( uint32_t )// xQueueBuffer用来保存队列结构体StaticQueue_t xQueueBuffer;// ucQueueStorage 用来保存队列的数据// 大小为:队列长度 * 数据大小uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];void vATask( void *pvParameters ){QueueHandle_t xQueue1;// 创建队列: 可以容纳QUEUE_LENGTH个数据,每个数据大小是ITEM_SIZExQueue1 = xQueueCreateStatic( QUEUE_LENGTH,ITEM_SIZE,ucQueueStorage,&xQueueBuffer ); }
复位
队列刚刚被创建时,里面没有数据;使用过程中可以调用xQueueReset()把队列恢复为初始状态,此函数原型为:
* pxQueue : 复位哪个队列;* 返回值: pdPASS(必定成功)*/
BaseType_t xQueueReset( QueueHandle_t pxQueue);
删除
删除队列的函数为vQueueDelete(),只能删除使用动态方法创建的队列,它会释放内存。原型如下:
void vQueueDelete( QueueHandle_t xQueue );
写队列
可以把数据写到队列头部,也可以写到尾部,这些函数有两个版本:在任务中使用、在ISR中使用。函数原型如下:
/* 等同于xQueueSendToBack* 往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait*/
BaseType_t xQueueSend(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait);/* * 往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait*/
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait);/* * 往队列尾部写入数据,此函数可以在中断函数中使用,不可阻塞*/
BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);/* * 往队列头部写入数据,如果没有空间,阻塞时间为xTicksToWait*/
BaseType_t xQueueSendToFront(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait);/* * 往队列头部写入数据,此函数可以在中断函数中使用,不可阻塞*/
BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);
这些函数用到的参数是类似的,统一说明如下:
参数 | 说明 |
xQueue | 队列句柄,要写哪个队列 |
pvItemToQueue | 数据指针,这个数据的值会被复制进队列, 复制多大的数据?在创建队列时已经指定了数据大小 |
xTicksToWait | 如果队列满则无法写入新数据,可以让任务进入阻塞状态, xTicksToWait表示阻塞的最大时间(Tick Count)。 如果被设为0,无法写入数据时函数会立刻返回; 如果被设为portMAX_DELAY,则会一直阻塞直到有空间可写 |
返回值 | pdPASS:数据成功写入了队列 errQUEUE_FULL:写入失败,因为队列满了 |
读队列
使用xQueueReceive()函数读队列,读到一个数据后,队列中该数据会被移除。这个函数有两个版本:在任务中使用、在ISR中使用。函数原型如下:
BaseType_t xQueueReceive( QueueHandle_t xQueue,void * const pvBuffer,TickType_t xTicksToWait );BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,void *pvBuffer,BaseType_t *pxTaskWoken);
参数说明如下:
参数 | 说明 |
xQueue | 队列句柄,要读哪个队列 |
pvBuffer | bufer指针,队列的数据会被复制到这个buffer 复制多大的数据?在创建队列时已经指定了数据大小 |
xTicksToWait | 果队列空则无法读出数据,可以让任务进入阻塞状态, xTicksToWait表示阻塞的最大时间(Tick Count)。 如果被设为0,无法读出数据时函数会立刻返回; 如果被设为portMAX_DELAY,则会一直阻塞直到有数据可写 |
返回值 | pdPASS:从队列读出数据入 errQUEUE_EMPTY:读取失败,因为队列空了。 |
查询
可以查询队列中有多少个数据、有多少空余空间。函数原型如下:
/** 返回队列中可用数据的个数*/
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );/** 返回队列中可用空间的个数*/
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
覆盖/偷看
当队列长度为1时,可以使用xQueueOverwrite()或xQueueOverwriteFromISR()来覆盖数据。 注意,队列长度必须为1。当队列满时,这些函数会覆盖里面的数据,这也以意味着这些函数不会被阻塞。 函数原型如下:
/* 覆盖队列* xQueue: 写哪个队列* pvItemToQueue: 数据地址* 返回值: pdTRUE表示成功, pdFALSE表示失败*/
BaseType_t xQueueOverwrite(QueueHandle_t xQueue,const void * pvItemToQueue);BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue,const void * pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);
如果想让队列中的数据供多方读取,也就是说读取时不要移除数据,要留给后来人。那么可以使用"窥视",也就是xQueuePeek()或xQueuePeekFromISR()。这些函数会从队列中复制出数据,但是不移除数据。这也意味着,如果队列中没有数据,那么"偷看"时会导致阻塞;一旦队列中有数据,以后每次"偷看"都会成功。 函数原型如下:
/* 偷看队列* xQueue: 偷看哪个队列* pvItemToQueue: 数据地址, 用来保存复制出来的数据* xTicksToWait: 没有数据的话阻塞一会* 返回值: pdTRUE表示成功, pdFALSE表示失败*/
BaseType_t xQueuePeek(QueueHandle_t xQueue,void * const pvBuffer,TickType_t xTicksToWait);BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer,);
总结
首先,队列的本质是任务与任务,任务与中断之间的一种数据交流的机制,队列的内存空间由两部分组成,一部分是队列结构体,一部分是队列存储区域,可以详细见队列结构体的图,对于理解队列的源码有很大帮助。使用队列的流程是:创建队列,写队列,读队列,删除队列,其中,队列是消耗性资源,一次只能唤醒一个阻塞的任务。
创建队列:主要负责为队列申请内存,然后调用函数prvInitialiseNewQueue()对队列进行初始化,也即初始化队列结构体的成员变量,其中还会对队列进行重置。
写队列:函数xQueueSend()等写队列函数都是调用xQueueGenericSend()函数,只是带入的参数不同,指定了不同的写入位置。
读队列:有两种,一种最常用的就是,读取队列项之后会删除队列项,”偷看“则不会删除队列项,二者都是从队列头开始读数据。
相关文章:

FreeRTOS队列
队列简介队列是一种任务到任务,任务到中断,中断到任务数据交流得一种机制。在队列中可以存储数量有限,大小固定得多个数据,队列中的每一个数据叫做队列项目,队列能够存储队列项目的最大数量称为队列的长度,…...

rancher2安装nfs-subdir-external-provisioner为PVC/PV动态提供存储空间(动态分配卷)
接上一篇《centos7部署rancher2.5详细图文教程》 一、 安装nfs服务 1. 所有节点都需要操作 $ # 下载 nfs 相关软件 $ sudo yum -y install nfs-utils rpcbind$ # 启动服务并加入开机自启 $ sudo systemctl start nfs && systemctl enable nfs $ sudo systemctl star…...

1.JAVA-JDK安装
前言:工具下载地址阿里云盘:Java-Jdk:https://www.aliyundrive.com/s/JpV55xhVq2A提取码: j53y一、jdk下载:前往Oracle官网可免费下载地址:https://www.oracle.com/java/technologies/downloads/ 此处我下载的是jdk8&a…...

Java必备小知识点4——数据类型、数组、位运算符
数据类型Java的数据类型由基本数据类型和引用类型基本数据类型和C语言的一致,除了基本类型其余的都是引用类型。引用类型主要有:类(class)、接口(interface)、数组、枚举(enum)、注解࿰…...

麦克风分类汇总
1.麦克风分类汇总 1)按声电转换原理分为:电动式(动圈式、铝带式),电容式(直流极化式)、压电式(晶体式、陶瓷式)、以及电磁式、碳粒式、半导体式等。 2)按声场作用力分为:…...

九龙证券|机制改革激发转融券活力 全面注册制释放两融展业新空间
在全面注册制准则规矩正式发布的同时,修订后的转融通事务规矩也应约与商场碰头。2月17日,中证金融发布《中国证券金融公司转融通事务规矩(试行)(2023年修订)》等规矩(简称“转融通新规”&#x…...

6——JVM调优工具详解及调优实战
Jmap、Jstack、Jinfo命令详解 Jmap 此命令可以用来查看内存信息,实例个数,以及占用内存大小 生成dump文件 把dump文件装入Jvisvalvm进行分析 Jstack Jstack加进程id查找死锁 Jstack找出占CPU最高的线程堆栈信息 top -p 进程号:显示进程…...

AcWing语法基础课笔记 第八章 C++ STL 第九章 位运算与常用库函数
第八章 C STL 第八章 C STL 1.#include <vector> 2.#include<queue> 3.#include <stack> 4.#include <deque> 5.#include <set> 6.#include<map> 第九章 位运算与常用库函数 STL是提高C编写效率的一个利器。 ——闫…...

Qt中的多线程
Qt中有多种方法实现多线程: QThreadQThreadPool和QPunnable(重用线程)Qt ConcurrentWorkerScript(QML中的线程)QThread 在上两篇文章中已经解释了,这里就不再赘述。 QThreadPoo和QRunnable(实现…...

React-Hooks怎样封装防抖和节流-面试真题
Debounce debounce 原意消除抖动,对于事件触发频繁的场景,只有最后由程序控制的事件是有效的。 防抖函数,我们需要做的是在一件事触发的时候设置一个定时器使事件延迟发生,在定时器期间事件再次触发的话则清除重置定时器ÿ…...

算法训练营 day51 动态规划 打家劫舍系列
算法训练营 day51 动态规划 打家劫舍系列 打家劫舍 198. 打家劫舍 - 力扣(LeetCode) 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#…...

【蓝桥集训】第六天——递归
作者:指针不指南吗 专栏:Acwing 蓝桥集训每日一题 🐾或许会很慢,但是不可以停下来🐾 文章目录1.树的遍历2.递归求阶乘3.求斐波那契数列1.树的遍历 一个二叉树,树中每个节点的权值互不相同。 现在给出它的后…...

react源码中的hooks
今天,让我们一起深入探究 React Hook 的实现方法,以便更好的理解它。但是,它的各种神奇特性的不足是,一旦出现问题,调试非常困难,这是由于它的背后是由复杂的堆栈追踪(stack trace)支…...

038.Solidity入门——25调用其他合约的方法
Solidity 提供了几种方式用于调用其他合约:方法描述直接调用使用 address.call 函数,可以向另一个合约发送消息并返回结果。低级调用使用 address.call 或 address.callcode 函数,可以执行一个外部合约中的代码。与直接调用不同,低…...

Revit项目浏览器的标准设置应用和快速视图样板?
一、Revit项目浏览器的标准设置应用 设计院阶段的BIM应用,主要是Revit出施工图方面,需要涉及到很多标准的制定方面的问题,而且这个标准不仅仅是一个命名标准,还有很多的符合本院的出图标准等等,本期就不做详细讨论&…...

安装MQTT Server遇到报错“cannot verify mosquitto.org‘s certificate”,该如何解决?
MQTT是基于发布/订阅的轻量级即时通讯协议,很适合用于低带宽、不稳定的网络中进行远程传感器和控制设备通讯等操作中。在我们的软件研发中,也经常使用MQTT协议进行消息通信等。今天来和大家分享一些关于在安装MQTT Server中遇到的疑难问题及解决思路。当…...

程序员如何向架构师转型?看完就明白该怎么做了
软件行业技术开发从业人员众多,但具备若干年开发经验的普通的开发人员往往面临个人发展的瓶颈,即如何从普通开发人员转型成高层次的系统架构师和技术管理人员。想成为一名架构师,应当具备全面的知识体系,需要进行系统的学习和实践…...

Flask入门(9):蓝图
目录9.蓝图9.1 概述9.2 蓝图项目结构结构1结构29.3 添加前缀9.4 静态文件9.5 模板9.6 构建 URLs9.蓝图 参考:http://www.pythondoc.com/flask/blueprints.html 9.1 概述 Flask 使用了 蓝图 的概念在一个应用或者跨应用中构建应用组件以及支持通用模式。 蓝图很好…...

跑步戴哪种耳机好,最适合运动跑步的蓝牙耳机
经常跑步使用的耳机,还是要选择佩戴着舒适以及牢固的运动耳机最为合适,在运动当中会遇到耳机掉落或者长时间佩戴耳道感到难受的现象发生,那么什么蓝牙耳机是最适合运动当中佩戴呢?下面这些耳机分享希望能够帮助大家。 1、南卡Run…...

微信小程序实现瀑布流布局
微信小程序实现瀑布流布局1、简单实例,纯图片后台返回图片高度https://blog.csdn.net/qq_45967222/article/details/1190318762、纯图片后台返回图片高度、通过wx.getImageInfo获取在线图片高度、按照奇数偶数来显示https://blog.csdn.net/baidu_35290582/article/d…...

2023最新网络工程师HCIA-Datacom“1000”道题库,光速刷题拿证
HCIA认证是华为认证体系的初级认证,可以说是网工进入IT行业的一张从业资格证! HCIA-Datacom考试覆盖数通基础知识 包括 TCP/IP 协议栈基础知识,OSPF 路由协议基本原理以及在华为路由器中的配置实现,以太网技术、生成树、VLAN 原…...

[蓝桥杯] 递归与递推习题训练
文章目录 一、递归实现指数型枚举 1、1 题目描述 1、2 题解关键思路与解答 二、递归实现排列型枚举 2、1 题目描述 2、2 题解关键思路与解答 三、递归实现组合型枚举 3、1 题目描述 3、2 题解关键思路与解答 四、带分数 4、1 题目描述 4、2 题解关键思路与解答 五、费解的开关…...

领航智能汽车信息安全新征程 | 云驰未来乔迁新址
2月20日,在北京朝阳百子湾东朝时代创意园,云驰未来迎来乔迁之喜,智能汽车和自动驾驶领域的行业领导、合作伙伴与客户、投资人及媒体嘉宾齐聚现场,共同见证云驰未来迈上新的发展征程。 作为中国智能网联汽车和自动驾驶信息安全行业…...

Kaldi语音识别技术(七) ----- 训练GMM
Kaldi语音识别技术(七) ----- GMM 文章目录Kaldi语音识别技术(七) ----- GMM训练GMMtrain_mono.sh 用于训练GMM训练GMM—生成文件训练GMM—final模型查看训练GMM—final.occs查看训练GMM—对齐信息查看训练GMM—fsts.*.gz查看训练GMM—tree决策树查看align_si.sh 用于对齐训练G…...

Java 集合基础
文章目录一、集合概念二、ArrayList1. 构造方法和添加方法2. 常用方法三、案例演示1. 存储字符串并遍历2. 存储学生对象并遍历3. 键盘录入学生对象并遍历一、集合概念 编程的时候如果要存储多个数据,使用长度固定的数组存储格式,不一定满足我们的需要&a…...

Day896.MySql的kill命令 -MySQL实战
MySql的kill命令 Hi,我是阿昌,今天学习记录的是关于MySql的kill命令的内容。 在 MySQL 中有两个 kill 命令: 一个是 kill query 线程 id,表示终止这个线程中正在执行的语句;一个是 kill connection 线程 id&#…...

L2-010 排座位
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。 输入格式࿱…...

C++的完美讲解,还不快来看看?
目录 简介: 创建C程序: Windows编译简介: Hello,C World! 简介: C融合了3中不同的编程传统:C语言代表的过程性传统、C在C语言基础上添加的类代表的面向对象语言的传统以及C模板支持的通用编程传统。一般来说,计算机语言…...

C语言学习_DAY_5_循环结构while和for语句【C语言学习笔记】
高质量博主,点个关注不迷路🌸🌸🌸! 目录 I. 案例引入 II. while语句 III. do while语句 IV. for语句 前言: 书接上回,判断结构已经解决,接下来是另一种很重要的结构:循环结构的实…...

JavaScript高级程序设计读书分享之4章——4.3垃圾回收
JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 4.3.3 性能 垃圾回收程序会周期性运行,如果内存中分配了很多变量,则可能造成性能损失,因此垃圾回收的 时间调度很重要。尤其是在内存有限的移动设备上,垃圾…...