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

【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);

关键优势解释

  1. 消除隐式依赖,明确函数职责
    烂代码问题:
    原函数 set_motor() 隐式依赖全局变量 motor_enabled 和 motor_speed。
    调用函数时,需先确保全局变量已正确赋值,函数行为与外部状态强耦合。

优化后:
函数 set_motor(enabled, speed) 明确要求传入 enabled 和 speed 参数。
函数仅对输入参数负责,行为完全由调用者控制,职责清晰。

  1. 避免副作用,提升代码可预测性
    烂代码问题:
    若其他函数意外修改了 motor_speed,set_motor() 的行为会悄然改变,引发难以追踪的 Bug。

优化后:
函数内部不依赖外部状态,相同的参数输入必然产生相同的行为,调试时只需关注参数来源,无需排查全局变量。

  1. 支持并发和复用
    烂代码问题:
    全局变量导致函数无法在多任务或中断环境中安全调用(例如:motor_speed 可能在函数执行中被其他线程修改)。

优化后:
参数传递的是瞬时值,函数执行期间状态不会变化。
还可轻松扩展为控制多个电机(例如通过额外参数指定电机ID)。

  1. 便于测试和维护
    烂代码问题:
    单元测试时需先初始化全局变量,测试用例互相干扰。

优化后:
直接测试函数逻辑:

// 测试用例:当 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…...

mysql 商城商品属性开发的动态解决方案

终极方案:动态属性解决方案 推荐使用 JSON 字段 虚拟列索引 的组合方案 结合灵活存储与查询优化,平衡扩展性与性能 完整实现步骤 步骤 1:创建基础表结构 CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NO…...

python利用open-cv和SSIM和特征值比较两个图片的相似性

以下是关于 **SSIM(结构相似性指数)** 和 **特征匹配** 的详细解释及实际示例,帮助理解它们的区别和应用场景: --- ### **1. SSIM(结构相似性指数)** #### **含义**: - **SSIM** 是一种衡量两…...

蔚来汽车智能座舱接入通义大模型,并使用通义灵码全面提效

为加速AI应用在企业市场落地,4月9日,阿里云在北京召开AI势能大会。阿里云智能集团资深副总裁、公共云事业部总裁刘伟光发表主题演讲,大模型的社会价值正在企业市场释放,阿里云将坚定投入,打造全栈领先的技术&#xff0…...

QT 老版本下载地址被禁 如何下载

前提: 想用老版本的QT 5.12 系列,但是QT官方已经封禁了国内IP 访问,5.15之前的版本,而且5.14.2是最后一个离线exe版本 ; Index of /official_releases/qt 基本不可用;全部改为在线安装; 收集了一下地址&am…...

VMWare Workstation Pro17.6最新版虚拟机详细安装教程(附安装包教程)

目录 前言 一、VMWare虚拟机下载 二、VMWare虚拟机安装 三、运行虚拟机 前言 VMware 是全球领先的虚拟化技术与云计算解决方案提供商,通过软件模拟计算机硬件环境,允许用户在一台物理设备上运行多个独立的虚拟操作系统或应用。其核心技术可提升硬件…...

【数据结构】红黑树超详解 ---一篇通关红黑树原理(含源码解析+动态构建红黑树)

一.什么是红黑树 红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。1972年出现,最初被称为平衡二叉B树。1978年更名为“红黑树”。是一种特殊的二叉查找树,红黑树的每一个节点上都有存储表示节点的颜色。每一个节点可以是…...

uni-app初学

文章目录 1. pages.json 页面路由2. 图标3. 全局 CSS4. 首页4.1 整体框架4.2 完整代码4.3 轮播图 swiper4.3.1 image 4.4 公告4.4.1 uni-icons 4.5 分类 uni-row、uni-col4.6 商品列表 uni-row、uni-col 小程序开发网址: 注册小程序账号 微信开发者工具下载 uniapp …...

PHP多维数组

在 PHP 中&#xff0c;多维数组是数组的数组&#xff0c;允许你存储和处理更复杂的数据结构。多维数组可以有任意数量的维度&#xff0c;但通常我们最常用的是二维数组&#xff08;数组中的数组&#xff09;。 首先来介绍一下一维数组&#xff0c; <?php//一维数组 $strAr…...

数学建模:针对汽车行驶工况构建思路的延伸应用

前言&#xff1a; 汽车行驶工况构建的思简单理解为将采集的大量数据进行“去除干扰、数据处理&#xff0c;缩减至1800S的数据”&#xff0c;并可达到等效替换的目的&#xff0c;可以使在试验室快速复现&#xff1b;相应的解决思路、办法可应用在 “通过能量流采集设备大量采集…...

go语言内存泄漏的常见形式

go语言内存泄漏 子字符串导致的内存泄漏 使用自动垃圾回收的语言进行编程时&#xff0c;通常我们无需担心内存泄漏的问题&#xff0c;因为运行时会定期回收未使用的内存。但是如果你以为这样就完事大吉了&#xff0c;哪里就大错特措了。 因为&#xff0c;虽然go中并未对字符串…...

当DRAM邂逅SSD:新型“DRAM+”存储技术来了!

在当今快速发展的科技领域&#xff0c;数据存储的需求日益增长&#xff0c;对存储设备的性能和可靠性提出了更高的要求。传统DRAM以其高速度著称&#xff0c;但其易失性限制了应用范围&#xff1b;而固态硬盘SSD虽然提供非易失性存储&#xff0c;但在速度上远不及DRAM。 为了解…...

论文精度:YOLOMG:基于视觉的无人机间检测算法——外观与像素级运动融合详解

论文地址:https://arxiv.org/pdf/2503.07115 1. 论文概述 论文标题:YOLOMG: Vision-based Drone-to-Drone Detection with Appearance and Pixel-Level Motion Fusion 作者:Hanqing Guo, Xiuxiu Lin, Shiyu Zhao 发表:未明确会议/期刊(推测为预印本或待发表) 核心贡献:…...

JS实现文件点击或者拖拽上传

B站看到了渡一大师课的切片&#xff0c;自己实现了一下&#xff0c;做下记录 效果展示 分为上传前、上传中和上传后 实现 分为两步 界面交互网络请求 源码如下 upload.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset&q…...

【KWDB 创作者计划】_ruby基础语法

以下是 Ruby 基础语法的简明总结&#xff0c;适合快速入门&#xff1a; 一、变量与常量 1. 局部变量 小写字母或下划线开头&#xff0c;作用域为当前代码块。 name "Alice" _age 20//局部变量附加&#xff1a;{{{{ 声明与命名规则 命名格式 以小写字母或下划线…...

Python Cookbook-5.15 根据姓的首字母将人名排序和分组

任务 想将一组人名写入一个地址簿&#xff0c;同时还希望地址簿能够根据姓的首字母进行分组&#xff0c;且按照字母顺序表排序。 解决方案 Python 2.4 的新 itertools.groupby 函数使得这个任务很简单: import itertools def qroupnames(name_iterable):sorted_names sort…...

2025 蓝桥杯省赛c++B组个人题解

声明 本题解为退役蒻苟所写&#xff0c;不保证正确性&#xff0c;仅供参考。 花了大概2个半小时写完&#xff0c;感觉比去年省赛简单&#xff0c;难度大概等价于 codeforces dv4.5 吧 菜鸡不熟悉树上背包&#xff0c;调了一个多小时 题目旁边的是 cf 预测分 所有代码均以通…...

Centos7.9 升级内核,安装RTX5880驱动

系统镜像下载 https://vault.centos.org/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso 系统安装步骤省略 开始安装显卡驱动 远程登录查看内核 [root192 ~]# uname -a Linux 192.168.119.166 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x8…...

Xdocreport实现根据模板导出word

只使用freemaker生成简单的word文档很容易&#xff0c;但是当word文档需要插入动态图片&#xff0c;带循环数据&#xff0c;且含有富文本时解决起来相对比较复杂&#xff0c;但是使用Xdocreport可以轻易解决。 Xdocreport既可以实现文档填充也可以实现文档转换&#xff0c;此处…...

运行一次性任务与定时任务

运行一次性任务与定时任务 文章目录 运行一次性任务与定时任务[toc]一、使用Job运行一次性任务1.创建一次性任务2.测试一次性任务3.删除Job 二、使用CronJob运行定时任务1.创建定时任务2.测试定时任务3.删除CronJob 一、使用Job运行一次性任务 1.创建一次性任务 &#xff08;…...

解决VS2022中scanf报错C4996

这个的原因是因为新版的VS认为scanf不安全&#xff0c;要去使用scanf_s&#xff0c;但在C语言中就需要scanf&#xff0c;所以我们只要以以下步骤解决就可以了。 只要加入宏定义即可 #define _CRT_SECURE_NO_WARNINGS 因为本人已经很少写小案例了&#xff0c;所以就用这个办法…...

当当平台商品详情接口设计与调用指南

当当平台商品详情接口设计与调用指南 接口名称 GET /api/product/detail 图书商品核心信息查询接口 请求参数说明 参数名称 类型 是否必填 说明 isbn string 是 国际标准书号(支持13位/10位) product_id string 否 平台内部商品编号&#xff08;与…...

sql server分析表大小

使用自动存储过程查询 EXEC sp_spaceused YourTableName; rows&#xff1a;表中的行数。reserved&#xff1a;表占用的总空间&#xff08;包括数据和索引&#xff09;。data&#xff1a;表数据占用的空间。index_size&#xff1a;索引占用的空间。unused&#xff1a;未使用的空…...

《AI大模型应知应会100篇》第13篇:大模型评测标准:如何判断一个模型的优劣

第13篇&#xff1a;大模型评测标准&#xff1a;如何判断一个模型的优劣 摘要 近年来&#xff0c;大语言模型&#xff08;LLMs&#xff09;在自然语言处理、代码生成、多模态任务等领域取得了显著进展。然而&#xff0c;随着模型数量和规模的增长&#xff0c;如何科学评估这些模…...

Linux基础9

一、日志管理 > 日志配置文件&#xff1a; > > ​ /var/log/messages #内核的消息以及各种服务的公共信息 > > ​ /var/log/dmesg #系统启动过程信息 > > ​ /var/log/cron #cron计划任务相关信息 > > ​ /var…...

hyper-v server服务器部署远程访问(我目前环境:hyper-v服务器+路由器+公网ip)

Hyper-v server部署(裸金属方式) 系统镜像下载安装# 下载地址:17763.737.190906-2324.rs5_release_svc_refresh_SERVERHYPERCORE_OEM_x64FRE_zh-cn_1.iso 安装的过程很简单,和安装Windows操作系统没啥区别,这里就不记录了。 安装过程可参考:安装Hyper-v Server 2016 部…...

【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)

文章目录 私有数据访问私有数据实例存储槽Solidity 中的数据存储方式1. storage(持久化存储)定长数组变长数组2. memory(临时内存)3. calldata可见性关键字私有数据存储风险安全措施私有数据 私有数据(Private Data)通常指的是只对特定主体可见或可访问的数据,在区块链…...

项目管理(高软56)

系列文章目录 项目管理 文章目录 系列文章目录前言一、进度管理二、配置管理三、质量四、风险管理五、真题总结 前言 本节主要讲项目管理知识&#xff0c;这些知识听的有点意思啊。对于技术人想创业&#xff0c;单干的都很有必要听听。 一、进度管理 二、配置管理 三、质量 四…...

程序化广告行业(79/89):技术革新与行业发展脉络梳理

程序化广告行业&#xff08;79/89&#xff09;&#xff1a;技术革新与行业发展脉络梳理 大家好&#xff01;一直以来&#xff0c;我都热衷于在技术领域不断探索&#xff0c;也深知知识共享对于进步的重要性。写这篇博客&#xff0c;就是希望能和大家一起深入研究程序化广告行业…...

零基础上手Python数据分析 (13):DataFrame 数据合并与连接 - 整合多源数据,构建完整分析视图

写在前面 —— 告别 VLOOKUP 烦恼,掌握 Pandas 合并连接利器,轻松整合分散数据 在前面的博客中,我们学习了如何读取数据、清洗数据、选取数据。 现在,我们已经能够处理单个 DataFrame 中的数据了。 然而,在实际的数据分析项目中,数据往往不是存储在一个单独的文件或表格…...