【C语言-全局变量】
【C语言-全局变量】
- 1.能局部就局部,别啥都往全局塞
- 2.尽量用结构体对零散变量封装
- 3.函数传参
- 4.静态变量+模块化
- 5 单例模式, 限制全局实例数量
- 6. 配置化全局参数——集中管理可调参数
- 7. 事件驱动架构:消息队列通信
- 策略选择建议
参考https://mp.weixin.qq.com/s/Ke134-r6dzz-WPYrdP8G7A并用deepseek扩展
1.能局部就局部,别啥都往全局塞
烂代码(全局变量版本):
uint16_t adc_raw; // 全局变量:整个程序都可以访问和修改
uint16_t adc_processed; // 全局变量:同样可以被任何地方修改 void get_adc_data(void) { adc_raw = ADC_Read(); // 直接存储到全局变量 adc_processed = adc_raw * 2; // 处理后存储到全局变量
}
好代码(局部变量版本):
uint16_t get_adc_data(void) { uint16_t raw = ADC_Read(); // 局部变量:只在函数内部存在 uint16_t processed = raw * 2; // 局部变量:处理数据 return processed; // 用完即走
}
我来举一个具体的例子来说明这两种方式的区别:
想象你是一个银行出纳员。全局变量就像是把所有客户的现金都放在一个开放的柜台上,任何人都可以接触和修改。而局部变量就像是每个客户都有自己的私密交易窗口,交易完成后窗口立即关闭。
全局变量的潜在问题:
意外修改风险
uint16_t adc_raw; // 全局变量 void process_adc() { adc_raw = ADC_Read();
} void debug_print() { // 突然有人在这里修改了adc_raw! adc_raw = 0;
} void main() { process_adc(); // 你可能期望adc_raw还是原来的值,但实际上已经被意外修改
}
局部变量的优势:
作用域受限
内存管理更高效
代码可读性更好
减少意外修改的可能性
uint16_t safe_adc_processing() { uint16_t raw = ADC_Read(); // 只在这个函数内存在 uint16_t processed = raw * 2; // 处理数据 return processed; // 函数结束,变量立即销毁
} void main() { uint16_t result = safe_adc_processing(); // 变量生命周期非常清晰和可控
}
实际应用场景
假设你在开发一个嵌入式温度监测系统:
// 不好的做法:全局变量到处乱飞
uint16_t global_temperature;
uint16_t global_humidity; void read_sensors() { global_temperature = read_temperature_sensor(); global_humidity = read_humidity_sensor();
}
// 好的做法:局部变量,职责清晰
typedef struct { uint16_t temperature; uint16_t humidity;
} SensorData; SensorData collect_sensor_data() { uint16_t temp = read_temperature_sensor(); uint16_t humid = read_humidity_sensor(); return (SensorData){ .temperature = temp, .humidity = humid };
}
关键收获
局部变量就像"用完即走"的快餐盒
全局变量像是一个公共食堂,容易被意外"污染"
局部变量提供了更好的封装和安全性
内存管理更加高效和可预测
建议:
尽可能使用局部变量
如果必须使用全局变量,要非常谨慎
使用const关键字进一步限制变量修改
考虑使用结构体和函数返回值来管理数据
2.尽量用结构体对零散变量封装
原始代码(散乱的全局变量):
// 全局变量分散,难以维护
uint8_t led_brightness; // LED亮度
uint8_t led_mode; // LED模式(0-常亮,1-呼吸)
bool led_enabled; // LED开关状态void update_led() {if (led_enabled) {if (led_mode == 0) {led_brightness = 100; // 常亮模式} else {led_brightness = 50; // 呼吸模式(示例简化)}}
}
优化后的代码(结构体封装):
// 将LED相关变量封装成结构体
typedef struct {uint8_t brightness; // 亮度uint8_t mode; // 模式(0-常亮,1-呼吸)bool enabled; // 开关状态
} LedController;// 初始化一个LED控制器实例
LedController led = {0, 0, false};void update_led() {if (led.enabled) {if (led.mode == 0) {led.brightness = 100; // 常亮模式} else {led.brightness = 50; // 呼吸模式}}
}
关键好处解释:
变量集中管理
所有LED相关的变量(亮度、模式、开关状态)被归拢到 LedController 结构体中,代码一目了然,不再需要全局搜索 led_ 开头的变量。
命名更简洁明确
原始代码中变量名需要加 led_ 前缀避免冲突(如 led_brightness),而结构体成员名无需冗余前缀,直接通过 led.brightness 访问,语义更清晰。
便于扩展和维护
若新增功能(例如增加颜色参数),只需在结构体中添加成员:
typedef struct {uint8_t brightness;uint8_t mode;bool enabled;uint32_t color; // 新增颜色参数
} LedController;
无需新增全局变量,改动集中且安全。
支持多实例化
如果需要控制多个LED,只需创建多个结构体实例:
LedController led1 = {0, 0, false};
LedController led2 = {0, 1, true};
而用全局变量实现多实例会导致变量名爆炸(如 led1_brightness, led2_mode)。
函数参数传递更高效
若需将LED状态传递给函数,只需传递结构体指针,而非多个单独变量:
void set_led_mode(LedController *led, uint8_t mode) {led->mode = mode;
}
总结
通过结构体封装,代码从“散乱的全局变量”变为“模块化的数据集合”,显著提升了可读性、可维护性和扩展性,尤其适合嵌入式系统中管理硬件外设(如定时器、LED、传感器)的状态。
3.函数传参
原始代码(依赖全局变量)
// 全局变量控制电机状态
uint8_t motor_speed = 0; // 电机转速
uint8_t motor_enabled = 0; // 电机开关// 全局函数直接操作全局变量
void set_motor() {if (motor_enabled) {PWM_SetDutyCycle(motor_speed); // 假设是PWM控制电机} else {PWM_Stop(); // 关闭电机}
}
优化后的代码(通过参数传递状态)
// 函数通过参数接收状态,不依赖全局变量
void set_motor(uint8_t enabled, uint8_t speed) {if (enabled) {PWM_SetDutyCycle(speed);} else {PWM_Stop();}
}
// 调用示例:开启电机,转速50%
set_motor(1, 50);
关键优势解释
- 消除隐式依赖,明确函数职责
烂代码问题:
原函数 set_motor() 隐式依赖全局变量 motor_enabled 和 motor_speed。
调用函数时,需先确保全局变量已正确赋值,函数行为与外部状态强耦合。
优化后:
函数 set_motor(enabled, speed) 明确要求传入 enabled 和 speed 参数。
函数仅对输入参数负责,行为完全由调用者控制,职责清晰。
- 避免副作用,提升代码可预测性
烂代码问题:
若其他函数意外修改了 motor_speed,set_motor() 的行为会悄然改变,引发难以追踪的 Bug。
优化后:
函数内部不依赖外部状态,相同的参数输入必然产生相同的行为,调试时只需关注参数来源,无需排查全局变量。
- 支持并发和复用
烂代码问题:
全局变量导致函数无法在多任务或中断环境中安全调用(例如:motor_speed 可能在函数执行中被其他线程修改)。
优化后:
参数传递的是瞬时值,函数执行期间状态不会变化。
还可轻松扩展为控制多个电机(例如通过额外参数指定电机ID)。
- 便于测试和维护
烂代码问题:
单元测试时需先初始化全局变量,测试用例互相干扰。
优化后:
直接测试函数逻辑:
// 测试用例:当 enabled=1, speed=50 时,是否调用了 PWM_SetDutyCycle(50)
set_motor(1, 50);
无需关心全局状态,测试更简单可靠。
4.静态变量+模块化
场景:温度传感器数据管理
假设我们需要管理一个温度传感器的采样值和报警标志。
原始代码(全局变量污染)
// 全局变量在头文件中暴露,所有文件都可随意修改
float temperature = 0.0f; // 当前温度
bool overheat_alarm = false; // 过热报警标志void read_temperature() {temperature = read_sensor(); // 读取传感器if (temperature > 100.0f) {overheat_alarm = true; // 触发报警}
}
问题:任何文件都可以直接修改 temperature 或 overheat_alarm,导致数据被意外篡改,调试困难。
优化代码(static变量 + 模块化)
// 文件:temperature.c
#include "sensor.h"static float temperature = 0.0f; // 仅本文件可见
static bool overheat_alarm = false; // 仅本文件可见// 内部温度更新逻辑
void read_temperature() {temperature = sensor_read();if (temperature > 100.0f) {overheat_alarm = true;} else {overheat_alarm = false;}
}// 对外接口:只读访问
float get_temperature() { return temperature; }
bool is_overheating() { return overheat_alarm; }
// 文件:main.c
#include "temperature.h"void main() {read_temperature(); // 更新温度if (is_overheating()) {printf("报警!当前温度:%.1f°C\n", get_temperature());}
}
关键优势分析
变量访问控制
通过 static 关键字将 temperature 和 overheat_alarm 限制在 temperature.c 文件内,外部文件无法直接修改,只能通过 get_temperature() 和 is_overheating() 接口读取。
强制数据封装
所有温度相关的操作(如传感器读取、报警判断)被集中到 temperature.c,修改温度值的唯一途径是通过 read_temperature() 函数,避免了数据被意外篡改。
接口与实现分离
外部只需关心 get_temperature() 和 is_overheating() 接口,无需了解内部如何存储温度值或判断报警逻辑,降低代码耦合度。
为什么不能直接在 get_counter() 中修改 counter?
假设有如下代码:
// 危险设计:在获取函数中修改值
uint32_t get_counter() {counter++; // 修改静态变量return counter;
}
问题分析
违反单一职责原则
get_counter() 的命名暗示它只是「获取」计数器值,但实际行为却包含「修改」计数器,这会导致以下问题:
调用者预期只是读取值,却意外触发计数器变化
调试时多次调用 get_counter() 会导致计数器异常增加
线程安全问题
如果在中断或多线程环境中调用 get_counter(),自增操作 counter++ 可能被打断,导致数据竞争(需原子操作保护)。
破坏封装性
计数器修改逻辑应该由明确的接口控制(如 count_task()),如果在获取函数中隐式修改,相当于开放了「后门」,违背模块化设计初衷。
正确设计模式
// 文件:counter.c
static uint32_t counter = 0;// 明确修改接口
void increment_counter() {counter++;
}// 明确读取接口
uint32_t get_counter() {return counter;
}// 可选:重置接口
void reset_counter() {counter = 0;
}
调用示例
// 正常使用
increment_counter(); // 明确的修改操作
printf("%u\n", get_counter()); // 明确的读取操作// 错误用法会被编译器拦截
counter = 100; // 编译错误:counter不可见
get_counter() = 50; // 编译错误:返回值不可修改
总结
通过 static + 模块化设计:
实现「模块内全局,模块外不可见」的受控访问
通过明确的接口函数(如 get_xxx()/set_xxx())管理数据
避免在查询函数中隐藏修改操作,保持代码可预测性
这种模式在嵌入式开发中广泛应用,尤其适合管理硬件状态(如传感器数据、设备标志位),既能保留全局变量的便利性,又确保系统可靠性。
5 单例模式, 限制全局实例数量
type struct{uint32_t speed;uint8_t mode;bool initialized;
}SPIController;static SPIController spi_instance = {0}; //唯一实例
SPIController* get_spi_instance(void){if(!spi_instance.initialized){spi_instance.speed = 1000 000;spi_instance.mode = 0;spi_instance.initialized = true;}return &spi_instance;
}void spi_set_speed)uint32_t speed)
{SPIController* spi = get_spi_instance();spi->speed = speed;//...
}
好处:
确保系统中只有一个 SPI 控制器实例
初始化延迟加载(第一次使用时初始化)
通过接口函数控制访问,避免直接操作结构体
6. 配置化全局参数——集中管理可调参数
场景:系统有多个可配置参数(如阈值、超时时间),需集中管理。
示例:温度控制系统参数
// 文件:config.h
typedef struct {float temp_high_threshold; // 高温阈值float temp_low_threshold; // 低温阈值uint16_t sampling_interval; // 采样间隔(ms)
} SystemConfig;// 默认配置(const 防止误修改)
extern const SystemConfig DEFAULT_CONFIG;// 文件:config.c
const SystemConfig DEFAULT_CONFIG = {.temp_high_threshold = 85.0f,.temp_low_threshold = -10.0f,.sampling_interval = 1000
};// 使用示例:
SystemConfig current_config = DEFAULT_CONFIG;void check_temperature(float temp) {if (temp > current_config.temp_high_threshold) {trigger_alarm();}
}
好处:
参数集中管理,修改时无需搜索分散的全局变量
通过 const 实现默认配置保护
支持运行时动态加载配置(如从EEPROM读取)
7. 事件驱动架构:消息队列通信
原理
核心思想:通过消息队列传递数据,取代共享全局变量,任务间解耦。
适用场景:多任务系统(如FreeRTOS)、中断与主循环通信、模块化系统设计。
示例:传感器数据采集与处理
// 文件:main.c(FreeRTOS示例)
#include "FreeRTOS.h"
#include "queue.h"// 定义传感器数据结构
typedef struct {float temperature;float humidity;uint32_t timestamp;
} SensorData;// 创建消息队列(容量10条数据)
QueueHandle_t sensor_queue = xQueueCreate(10, sizeof(SensorData));// 传感器任务:采集数据并发送到队列
void sensor_task(void *pvParams) {SensorData data;while (1) {data.temperature = read_temperature_sensor();data.humidity = read_humidity_sensor();data.timestamp = xTaskGetTickCount();xQueueSend(sensor_queue, &data, portMAX_DELAY); // 阻塞直到发送成功vTaskDelay(pdMS_TO_TICKS(1000)); // 每1秒采集一次}
}// 处理任务:从队列接收数据并处理
void process_task(void *pvParams) {SensorData data;while (1) {if (xQueueReceive(sensor_queue, &data, portMAX_DELAY)) {if (data.temperature > 50.0f) {trigger_alarm(); // 触发高温报警}log_to_sd_card(&data); // 记录到SD卡}}
}// 主函数中启动任务
int main() {xTaskCreate(sensor_task, "Sensor", 128, NULL, 2, NULL);xTaskCreate(process_task, "Process", 128, NULL, 1, NULL);vTaskStartScheduler();return 0;
}
策略选择建议
场景 推荐策略 示例
单一函数内部状态维护 状态局部化(static) 传感器滤波、错误计数器
多实例硬件控制 面向对象设计(结构体) 管理多个ADC、PWM控制器
多任务/中断间数据传递 事件驱动(消息队列) 传感器数据采集与处理分离
系统级配置参数 结构体封装 + 单例模式 存储网络配置、系统参数
相关文章:
【C语言-全局变量】
【C语言-全局变量】 1.能局部就局部,别啥都往全局塞2.尽量用结构体对零散变量封装3.函数传参4.静态变量模块化5 单例模式, 限制全局实例数量6. 配置化全局参数——集中管理可调参数7. 事件驱动架构:消息队列通信策略选择建议 参考https://mp.weixin.qq.c…...
Downlink Sensing in 5G-Advanced and 6G: SIB1-assisted SSB Approach
摘要——本文研究了利用现有5G NR信号进行网络侧集成感知与通信(ISAC)的潜力。通常,由于其频繁的周期性可用性和波束扫描特性,同步信号块(SSB)是适合用于下行感知的候选信号。然而,正如本文所示…...
PCIe 5.0光学SSD原型问世!
近日,Kioxia Corporation(铠侠)、AIO Core Co., Ltd. 和 Kyocera Corporation(京瓷)联合宣布成功开发了一款支持 PCIe 5.0 接口的光学 SSD 原型。该技术旨在通过光接口替换传统的电接口,从而显著增加计算设…...
JDK(Java Development Kit)从发布至今所有主要版本 的详细差异、新增特性及关键更新的总结,按时间顺序排列
以下是 JDK(Java Development Kit)从发布至今所有主要版本 的详细差异、新增特性及关键更新的总结,按时间顺序排列: 1. JDK 1.0 (1996) 发布年份:1996年1月23日关键特性: Java首次正式发布。核心语言特性…...
【3分钟准备前端面试】yarn
目录 Yarn核心概念核心机制解析工作流与命令详解高级功能剖析性能优化策略常见问题解决方案Yarn与...
[16届蓝桥杯 2025 c++省 B] 移动距离
思路:这题很多人肯定一眼就觉得是直线,因为无限方案,怎么走随便你,极限状态会误以为是直线,实际上你会发现,只有往右走是直线,往上走时一个弧线操作,就算你一下往右,一下…...
二叉树(中)-- 堆
堆是一个独立的数据结构,堆是一个二叉树。堆和栈几乎没有什么关联 堆是一个完全二叉树,可以用数组存储 大堆: 任何一个父亲都大于等于孩子小堆: 任何一个父亲都小于等于孩子 请注意,小堆大堆并不一定是升序或降序&…...
艾伦·图灵:计算机科学与人工智能之父
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 艾伦图灵:计算机科学与人工智能之父 一、天才的诞生与早期生涯 1912年6月…...
Doris 安装部署、实际应用及优化实践:对比 ClickHouse 的深度解析
在实时分析、报表系统以及高并发 OLAP 查询等场景中,列式存储数据库因其卓越的查询性能逐渐成为主流。Doris 和 ClickHouse 是近年来最受欢迎的两款开源 OLAP 引擎,本文将系统介绍 Doris 的安装部署、应用场景及优化实践,并与 ClickHouse 做一…...
Vue的学习总结-day02
一、Vue的基本语法 1、Vue.js 使用双大括号 {{ }} 来表示文本插值: <template><div class"demo">{{msg}}</div> </template> 2、指令 v-bind:动态绑定一个或多个特性,或一个组件 prop。 <template…...
MySQL 中查询 VARCHAR 类型 JSON 数据的
在数据库设计中,有时我们会将 JSON 数据存储在 VARCHAR 或 TEXT 类型字段中。这种方式虽然灵活,但在查询时需要特别注意。本文将详细介绍如何在 MySQL 中有效查询存储为 VARCHAR 类型的 JSON 数据。 一、问题背景 当 JSON 数据存储在 VARCHAR 列中时&a…...
Spring Boot 的启动流程
Spring Boot 是一个用于简化 Spring 应用程序开发的框架,它通过自动配置和约定优于配置的原则,大大降低了开发者的工作量。下面我们将深入探讨 Spring Boot 的启动流程,帮助你理解其背后的工作机制。 1. 启动入口 Spring Boot 应用的启动入…...
JMeter的接口测试步骤
创建测试计划 新建测试计划: 打开 JMeter,右键点击 Test Plan,选择 Add -> Threads (Users) -> Thread Group。双击 Thread Group,设置线程数(用户数)、循环次数等参数。 添加取样器(S…...
Linux基础14
一、搭建LAMP平台 安装包:mariadb-server、php、php-mysqlnd、php-xml、php-json 搭建平台步骤: php步骤: 创建网页:index.php 网页内编写php语言: > eg:<?p…...
七种数码管驱动/LED驱动综合对比——《器件手册--数码管驱动/LED驱动》
十四、数码管驱动/LED驱动 名称 工作原理 应用场景 优缺点 特点 LED驱动 LED驱动的核心是为发光二极管提供稳定的电流。LED的亮度与电流成正比,而其正向电压相对稳定。驱动电路需要根据电源电压和LED的正向电压,通过限流电阻或恒流芯片来控制电流。…...
【25软考网工笔记】第二章 数据通信基础(2) 信道延迟计算
目录 一、信道延迟 1. 线路延迟 1)线路延迟与传输距离的关系 2)光纤线路与电缆线路的传播速度 3)线路延迟计算示例:1000米电缆的延迟 2. 发送延迟 1)发送延迟的定义与计算 2)发送延迟的影响因素 3.…...
代码随想录第16天:(二叉树)
一、最大二叉树(Leetcode 654) class Solution:def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:# 基础条件:当数组只有一个元素时,直接返回该元素构建的二叉树节点if len(nums) 1:return TreeNode(nums[…...
Android activity属性taskAffinity的作用
1. taskAffinity的基本概念 在Android开发中,taskAffinity是一个定义在标签中的属性,用于指定Activity与哪个任务(Task)相关联。默认情况下,应用的所有Activity都共享同一个任务堆栈,其taskAffinity值为应…...
Vuex Actions 多参数传递的解决方案及介绍
Vuex Actions 多参数传递的解决方案及介绍 引言 在Vuex状态管理模式中,Actions 扮演着至关重要的角色。它主要用于处理异步操作,并且可以提交 Mutations 来修改全局状态。然而,在实际开发中,我们常常会遇到需要向 Actions 传递多…...
SQL学习--基础语法学习
SQL和excle对比 学习目标 单表查询 项目背景 SQL 练习环境 SQL Online Compiler - Next gen SQL Editor 商品信息表:https://study-zhibo.oss-cn-shanghai.aliyuncs.com/test/%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E8%A1%A8.csv 订单明细表:https://…...
ProfibusDP转ModbusTCP接流量计技巧
ProfibusDP转ModbusTCP接流量计技巧 在现代工业自动化系统中,设备的互联互通至关重要。为了实现不同协议设备之间的数据交换与统一管理,Profibus DP主站转Modbus TCP网关成为了一个重要的解决方案。本文将详细介绍这一转换方案及其在电磁流量计中的应用…...
【数据结构与算法】ArrayList 和 顺序表
文章目录 🌲List🌲1. 线性表🌲2. 顺序表🌿2.1 MyArrayList2.1.1 类中重写所有接口方法1.新增元素2.在pos位置新增元素(指定位置)3.判定是否包含了某个特定元素 4.查找特定元素对应的位置 5.获取pos下标的元素 6.给pos位置的元素替…...
VMware Fusion Pro/Player 在 macOS 上的完整安装与使用指南
VMware Fusion Pro/Player 在 macOS 上的完整安装与使用指南—目录 一、VMware 产品说明二、下载 VMware Fusion三、安装前准备四、安装 VMware Fusion步骤 1:安装程序步骤 2:首次启动配置步骤 3:输入许可证 五、创建虚拟机步骤 1:…...
GESP2025年3月认证C++七级( 第三部分编程题(1)图上移动)
参考程序(动态规划) #include <cstdio> using namespace std; const int K 25; // 最大步数 多开一点 const int N 505; // 最大结点数 const int E N << 1; // 最多边数(因为是无向图,每条边…...
将LINUX系统本机文件上传到LINUX虚拟机,未联网的情况下
将LINUX系统本机文件上传到LINUX虚拟机,未联网的情况下 1.将需要上传的文件,归档为.iso镜像文件 命令:mkisofs -r -o myiso.iso /iso/tool 2.打开虚拟机,选择需要挂载的光盘 3.创建挂载点,一般在/mnt目录下 mkdir /mnt/tool 4.临时挂载镜像 mount /dev/cdrom /mnt/tool 5.需要…...
Selenium之Actions事件
鼠标、键盘组合键 在使用selenium的时候,有的时候我们需要鼠标单击、双击、拖动;或者是按下键盘的某个键,松开某个按键,以及组合键的使用;今天我们就来看一看,怎么样实现上面的操作 先把准备工作做好&…...
高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第三章微分中值定理与导数的应用同步测试卷 A 卷
第三章微分中值定理与导数的应用同步测试卷 A 卷 一、单项选择题(本大题共5小题,每小题3分,总计15分) 1. 2. 3. 4. 5. 二、填空题(本大题共5小题,每小题3分,总计15分) 6. 7. 8. 9. 10. 三、求解下列各题(本大题共5小题,每小题6分,总计…...
使用Vscode排除一些子文件搜索
打开用户/工作区设置 全局生效:打开命令面板(CtrlShiftP 或 CmdShiftP),搜索并选择 Preferences: Open User Settings (JSON)。 仅当前项目生效:在项目根目录下创建 .vscode/settings.json 文件(如果不存在…...
《前端面试题之 CSS篇(第一集)》
目录 1、CSS的盒模型2、CSS选择器及其优先级3、隐藏元素的方法有那些4、px、em、rem的区别及使用场景5、重排、重绘有什么区别6、水平垂直居中的实现7、CSS中可继承与不可继承属性有哪些8、Sass、Less 是什么?为什么要使用他们?9、CSS预处理器/后处理器是…...
第九天 开始Unity Shader的学习之单张纹理
Unity Shader的学习笔记 第九天 开始Unity Shader的学习之单张纹理 文章目录 Unity Shader的学习笔记前言一、基础纹理二、单张纹理① Properties② Cg代码块的变量③ 顶点着色器和片元着色器的结构体(a2v 和 v2f)④ 顶点着色器vert⑤ 片元着色器 frag效果展示 总结 前言 前几…...
Linux-内核驱动-led
登记设备号(后面可以动态分配) 自己定义内核函数 登记设备名字和功能 exit和init在内核启动自动执行 这样定义直接操作物理地址 ioctl 定义了设备文件的各种操作,并准备将其注册到内核中。 代码中声明了一个cdev结构体变量cdev,这…...
Web 项目实战:构建属于自己的博客系统
目录 项目效果演示 代码 Gitee 地址 1. 准备工作 1.1 建表 1.2 引入 MyBatis-plus 依赖 1.3 配置数据库连接 1.4 项目架构 2. 实体类准备 - pojo 包 2.1 dataobject 包 2.2 request 包 2.3 response 包 2.3.1 统一响应结果类 - Result 2.3.2 用户登录响应类 2.3.3…...
C++算法(1):stringstream详解,高效字符串处理与类型转换的利器
什么是stringstream? stringstream是C标准库中的一个类,定义在<sstream>头文件中。它提供了一种方便的方式来处理字符串与其他数据类型之间的转换和格式化操作。stringstream结合了istringstream和ostringstream的功能,既可以用于输入…...
【前端】【css】flex布局详解
Flex 布局(Flexible Box Layout,弹性盒子布局)是 CSS3 中的一种布局模式,用于在容器中更高效地分配空间并对齐内容,即使它们的大小是动态未知的。它非常适用于响应式设计。 一、Flex 布局的基本概念 1. 启用 Flex 布局…...
Python Cookbook-5.15 根据姓的首字母将人名排序和分组
任务 想将一组人名写入一个地址簿,同时还希望地址簿能够根据姓的首字母进行分组,且按照字母顺序表排序。 解决方案 Python 2.4 的新 itertools.groupby 函数使得这个任务很简单: import itertools def qroupnames(name_iterable):sorted_names sort…...
深入探析C#设计模式:访问者模式(Visitor Pattern)的原理与应用
引言 在软件开发中,设计模式为我们提供了高效、可维护的解决方案。而在众多设计模式中,访问者模式(Visitor Pattern)以其独特的结构和应用场景,在复杂系统中发挥着重要作用。本文将深入讲解访问者模式的定义、原理、优…...
2025蓝桥杯省赛C/C++研究生组游记
前言 至少半年没写算法题了,手生了不少,由于python写太多导致行末老是忘记打分号,printf老是忘记写f,for和if的括号也老是忘写,差点连&&和||都忘记了。 题目都是回忆版本,可能有不准确的地方。 …...
RPA VS AI Agent
图片来源网络 RPA(机器人流程自动化)和AI Agent(人工智能代理)在自动化和智能化领域各自扮演着重要角色,但它们之间存在显著的区别。以下是对两者区别的详细分析: 一、定义与核心功能 RPA(机…...
软件信息化项目等级分类评定表
对信息化项目进行分类评级管理,能够优化资源配置、保障项目成效。可从项目性质、规模、战略价值等维度分类,依据技术、风险、收益等指标评级,进而实现精细化管理。 分类管理 按项目性质分类:可分为业务流程优化项目,如优化企业采购流程的信息化项目,旨在提升效率;还有信…...
从0~1搭建自动化备份全网服务器数据平台
目录 摘要: 一、项目背景 1.1 rsync简介 作用: 特点: 语法: 1.2 项目需求 配置需求: 二、项目环境 2.1 项目拓扑结构 2.2 软硬件环境清单 三、任务清单 3.1 项目环境搭建 3.2 服务器部署 Web服务器搭建部署&#…...
用户态视角理解内核ROP利用:快速从shell到root的进阶
用户态视角理解内核ROP利用:快速从shell到root的进阶 一、摘要 本文仅限于快速从用户态向内核态入门,可能会有很多不严谨的地方,存在问题请及时告知感谢!本文旨在通过对比用户态 ROP 利用和内核 ROP 利用,揭示两者在利用手法上的相似性。通过分析用户态漏洞利用的流程,结合…...
我又叕叕叕更新了~纯手工编写C++画图,有注释~
本次更新内容: 优化性能,朗读 提前申明:如果运行不了,请到主页查看RedpandaDevc++下载,若还是不行就卸了重装。 版本号:1.26.36 779行 24690字 最终结果预览 代码预览 //版本号 :v1.26.36 //最终归属权为作者(饼干帅成渣)所有 //禁止转载 //仅供学习,不得用于违法 #…...
【家政平台开发(37)】家政平台蜕变记:性能优化与代码重构揭秘
本【家政平台开发】专栏聚焦家政平台从 0 到 1 的全流程打造。从前期需求分析,剖析家政行业现状、挖掘用户需求与梳理功能要点,到系统设计阶段的架构选型、数据库构建,再到开发阶段各模块逐一实现。涵盖移动与 PC 端设计、接口开发及性能优化,测试阶段多维度保障平台质量,…...
基于springboot+vue的秦皇岛旅游景点管理系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 用户登录 旅游路…...
图像预处理-翻转与仿射变换
一.图像翻转 cv2.flip(img,flipcode) 参数 - flipcode : 指定翻转类型的标志,为0,表示沿x轴翻转,>0(默认1) 表示沿y轴翻转,为 <0(默认-1) 表示水平垂直翻转 OpenCV中,图片的镜像旋转以图像的中心为原点 impo…...
[ABC400F] Happy Birthday! 3 题解
考虑正难则反。问题转化为: 一个环上有 n n n 个物品,颜色分别为 c o l i col_i coli,每次操作选择两个数 i , j i, j i,j 使得 ∀ k ∈ [ i , j ] , c o l k c o l i ∨ c o l k 0 \forall k \in [i, j], col_k col_i \lor col_k …...
使用nuxt3+tailwindcss4+@nuxt/content3在页面渲染 markdown 文档
nuxt3tailwindcss在页面渲染 markdown 文档 页面效果 依赖 “nuxt/content”: “^3.4.0” “tailwindcss”: “^4.0.10” “nuxt”: “^3.16.2” “tailwindcss/vite”: “^4.0.10” tailwindcss/typography (这个是格式化 md 样式用的) 注意: 这里nuxt/content…...
畅游Diffusion数字人(23):字节最新表情+动作模仿视频生成DreamActor-M1
畅游Diffusion数字人(0):专栏文章导航 前言:之前有很多动作模仿或者表情模仿的工作,但是如果要在实际使用中进行电影级的复刻工作,仅仅表情或动作模仿还不够,需要表情和动作一起模仿。最近字节跳动提出了一个表情+动作模仿视频生成DreamActor-M1。 目录 贡献概述 核心动…...
多模态学习分析(MLA)驱动高中差异化教学策略研究
一、引言 1.1 研究背景 在当今时代,教育数字化转型的浪潮正席卷全球,深刻地改变着教育的面貌。这一转型不仅是技术的革新,更是教育理念、教学模式和教育管理的全面变革。随着互联网、大数据、人工智能等现代信息技术在教育领域的广泛应用&a…...
为什么ASCII的A是65[特殊字符]
为什么ASCII的A是65 1. ASCII是怎么来的 ASCII是1960年代美国标准协会制定的,目的是统一计算机字符编码。它们要在**7个比特位(0-127)**里,塞下所有英文字符,数字,标点和控制符。 2. 为什么A是65&#x…...