单片机/C语言八股:(四)volatile 和 static 关键字的作用

上一篇 下一篇
C 语言编译器的优化功能

1)volatile 关键字的作用是什么?

volatile:[adj] 易变的

C/C++ 编译器具有优化功能:在不改变程序逻辑的前提下,让生成的代码运行更快、体积更小或更省资源。

当开启优化时,处理器会把一些高频使用的变量的值放进缓存或寄存器中,这个时候它就不从内存中取了,虽然这可以提高效率,但当这个变量的值被修改了之后(比如被多线程或中断程序修改了),CPU 没有重新访问内存,就会造成数据不一致的问题。

解决方法就是使用 volatile 关键字。

volatile 是一个类型修饰符,用于告诉编译器,该变量的值可能会被改变(是不稳定的)。然后不论如何优化,编译器每次访问该变量时,都会直接从其内存地址中读取数据 (即:volatile 是让 CPU 直接去变量内存地址里去读取数据,而不是去缓存读取数据,用于防止编译器优化此变量 )。

使用:

c 复制代码
volatile int flag = 1;

2)static 关键字的作用是什么?

static:[adj] 静态的

static 变量称为静态存储类型的变量,所谓静态就是变量在程序运行期间一直存在。

static 变量的特点如下:

  • 在内存中以固定地址存放,而不是以堆栈方式存放(程序运行多次之后,依然存在同一地址);
  • 只要程序没结束,此变量就不会消失,即使放在子函数中被反复调用,每次调用的时候,都会保留调用结束的值;
  • static 修饰的全局变量,其他文件无法使用(其他文件即使使用 extern 声明,也无法访问该变量);
  • 如果没有初始化,那么静态变量的初始值默认是 0 。

举例,有如下程序:

c 复制代码
#include <stdio.h>
void fun() 
{
	int a=10;
	a++;
	printf("%d %p\n",a,&a);
}

int main()
{
	int i=0;
    while(i<5)
    {
    	fun();
    	i++;
    }
    return 0;
}

程序运行之后的结果为(运行两次):

c 复制代码
/* 第一次运行结果 */
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
    
/* 第二次运行结果 */
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
    
// 两次运行,分配的地址都是不确定的

现在将变量 a 定义为静态变量,并且不初始化:

c 复制代码
#include <stdio.h>
void fun() 
{
	static int a;
	a++;
	printf("%d %p\n",a,&a);
}

int main()
{
	int i=0;
    while(i<5)
    {
    	fun();
    	i++;
    }
    return 0;
}

程序运行之后的结果为(运行两次):

c 复制代码
/* 第一次运行结果 */
1 00007ff74fb4a000
2 00007ff74fb4a000
3 00007ff74fb4a000
4 00007ff74fb4a000
5 00007ff74fb4a000
    
/* 第二次运行结果 */
1 00007ff74fb4a000
2 00007ff74fb4a000
3 00007ff74fb4a000
4 00007ff74fb4a000
5 00007ff74fb4a000
    
// 两次运行,分配的地址都是固定的,并且初始值为 0 (+1后才打印)

总结:

  • 定义静态局部变量:延长生命周期,保持值不变
  • 定义静态全局变量:限制作用域,别的文件不可调用
  • 定义静态函数:限制函数作用域,别的文件不可调用
c 复制代码
// 1. 静态局部变量
static int count = 0;

// 2. 静态全局变量
static int globalVar;

// 3. 静态函数
static void localFunc(void) {}

相关推荐
zhangfeng11338 小时前
scp 命令的使用方法 什么软件支持 .git bash xshell .openssh
开发语言·git·bash
披着假发的程序唐8 小时前
STM32 H743 MPU的配置使用方法
linux·c语言·c++·驱动开发·stm32·单片机·mcu
東隅已逝,桑榆非晚8 小时前
深⼊理解指针(3)
c语言·数据结构·笔记·算法·排序算法
泓博8 小时前
docker ubuntu源码安装openclaw的常见问题
java·linux·开发语言·ai
li星野8 小时前
二叉树十题通关:从层序遍历到序列化(Python + C++)
开发语言·c++·python·学习
后季暖8 小时前
python装饰器解释
开发语言·python
南境十里·墨染春水8 小时前
线程池学习(一) 理解 进程 线程 协程及上下文切换
java·开发语言·学习
知兀8 小时前
@Accessors(chain = true)和@Builder链式风格差异
java·开发语言
Mr.H01278 小时前
C语言MQTT学习系列(3篇):第一篇:从零开始学MQTT(C语言版):入门必看,跑通最简Demo
c语言·网络·学习
zhangfeng113310 小时前
openclaw skills 小龙虾技能 通讯仿真 matlab skill Simulink Agentic Toolkit,通过kimi找到,mcp通讯
开发语言·matlab·openclaw·通讯仿真