C语言 static 关键字三大作用

一、修饰局部变量(函数内部变量)

  1. 生命周期改变 普通局部变量:函数调用时创建,调用结束销毁,存栈区。 static 局部变量:存静态全局区 ,程序运行全程只初始化一次,函数结束不销毁,值保留。

  2. 初始化时机 只在第一次进入函数时赋值,后续调用沿用上次结果。

    void test() {
    static int a = 0; // 仅首次赋值0
    a++;
    printf("%d ", a);
    }
    int main() {
    test(); // 1
    test(); // 2
    test(); // 3
    return 0;
    }

  3. **作用域不变:**只能当前函数内访问。

现象分析:无static(普通局部变量)样式失效、加static正常显示底色

一、核心原因:内存存储区域不同

  1. 不加 static:lv_style_t style;(栈局部变量)

  2. 内存位置 :存放在函数栈内存 栈内存是临时内存,函数每次执行时分配,函数执行完毕立刻释放;

  3. 结构体数据丢失 lv_style_init、lv_style_set_bg_color 给栈内style赋值后,当LVGL渲染控件时,函数栈帧可能已经销毁,style结构体内存被栈里其他数据覆盖、变成随机脏数据;

  4. 表现:控件读取到错乱的样式参数,底色不生效,显示白色空白方块。

  5. 加 static:static lv_style_t style;(静态局部变量)

  6. 内存位置 :存放在全局静态数据段,程序全程不销毁;

  7. 数据永久保留 初始化后的颜色、样式参数会一直保存在静态内存,LVGL渲染时随时能读取完整有效的样式数据;

  8. 表现:蓝色底色正常渲染。


二、补充栈内存风险(LVGL场景重点)

  1. lv_style_t 是体积较大的结构体,栈空间容量很小(模拟器/单片机通常几KB~十几KB);

  2. 频繁调用该GUI函数时,栈会反复开辟、释放大结构体,极易出现栈溢出、内存脏数据、程序崩溃;

  3. 单片机嵌入式场景下,大结构体一律推荐用static修饰,放到静态区,避免占用栈。


三、优化代码(只初始化一次样式,减少重复运算)

当前代码每次调用函数都会执行lv_style_init重复初始化,浪费算力,优化后:

复制代码
void my_gui(void)
{
    static lv_style_t style;
    static uint8_t style_ready = 0; // 标记是否已初始化
    if(!style_ready)
    {
        lv_style_init(&style);
        lv_style_set_bg_color(&style,lv_color_hex(0x0000a0));
        style_ready = 1;
    }

    lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
    lv_obj_add_style(obj1,&style,LV_STATE_DEFAULT);
}

四、总结对照表

写法 内存区域 数据生命周期 LVGL表现 风险
lv_style_t style; 栈 仅本次函数调用 底色失效、空白 栈溢出、内存脏数据
static lv_style_t style; 静态全局区 程序全程有效 底色正常显示 无栈压力,稳定

二、修饰全局变量(函数外部)

普通全局变量:作用域为整个工程 ,其他.c文件用extern可访问。 static全局变量:仅限当前.c文件,其他源文件无法引用,实现文件隔离,避免命名冲突。

复制代码
// a.c
static int num = 10; // 仅a.c可用
// b.c
extern int num; // 报错,找不到num

三、修饰函数

普通函数:全工程可见,其他文件可直接调用。 static函数:仅当前.c文件内部调用,对外隐藏接口,封装模块。

复制代码
// a.c
static void func() {
    // 只能在a.c里调用
}

总结表格

修饰对象 核心效果 存储位置 作用域
局部变量 只初始化一次,值持久保存 静态区 当前函数
全局变量 限制为本文件私有 静态区 当前源文件
函数 函数仅本文件可见 代码段 当前源文件

补充要点

  1. static不会改变变量作用域,只会改变生命周期/链接属性;

  2. static局部变量默认初始值0,普通栈变量随机脏值;

  3. 嵌入式开发常用static保存设备状态、计数。

相关推荐
银河技术4 小时前
从脚本到 Operator:用 Go 构建可靠的微服务自动扩缩容控制器
开发语言·微服务·golang
GIS数据转换器6 小时前
地下空间综合管廊运营管理平台
大数据·开发语言·人工智能·经验分享·perl
lhbweilai8 小时前
分析FreeRTOS内核对象API的源码实现(四)
c语言·stm32·单片机
Wang's Blog11 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
inrichtt11 小时前
第八课时:SPI总线揭秘:四线全双工通信的奥
c语言·数据结构·stm32·单片机·嵌入式硬件
砚底藏山河12 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
今年下半年12 小时前
AI智能体项目实战记录(02):初始化 Python 项目
开发语言·人工智能·python·fastapi
Williamtym12 小时前
PickGo Lab实践:用浏览器、Python和MCP串起机器人搬运仿真
开发语言·python·机器人
DongQiShanRen12 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CS创新实验室12 小时前
Python 对象“死“了之后去了哪?——引用计数与分代垃圾回收
开发语言·jvm·python