C中__IO和静态关键字有啥用?
Posted
技术标签:
【中文标题】C中__IO和静态关键字有啥用?【英文标题】:What is the use of __IO & static keywords in C?C中__IO和静态关键字有什么用? 【发布时间】:2018-12-22 12:56:49 【问题描述】:我正在检查一些为 STM32F 微控制器编写的代码,我发现在初始化变量之前使用了这些关键字。我想知道使用“__IO”和“static”关键字有什么意义?
这行代码是这样给出的:
static __IO uint32_t sysTickCounter;
【问题讨论】:
__IO
可能是一个宏,可以是volatile
或什么都不是
static
,嗯,这意味着它仅限于这个范围(文件或函数)但全局(不是自动变量)
当然,如果您包含 C 文件(不推荐),那么该变量在您包含的文件中可见
你不需要static
,除非变量在其他文件中定义为同名。
我们不是个人辅导服务。评论不适用于扩展讨论或询问/回答更多问题。您的所有问题都将由教科书解答。请拿一个;不要尝试从晦涩难懂的在线教程或 youtube 视频中学习 C。
【参考方案1】:
__IO
/ volatile
__IO
不是 C 关键字。 __IO
是 volatile
的宏 - 在 STM32 标准外设库头文件中定义。例如,在core_cm4.h
(可能在CMSIS
子文件夹中),你会发现
#define __IO volatile
(如果你使用gcc
的-E
选项只使用预处理阶段,你可以看到宏的展开。)
反过来,volatile
关键字通常应用于变量以防止编译器“优化它”。这在嵌入式系统中很有用 - 变量可能在中断中使用 - 编译器优化可能会导致问题。
简短的例子...
int main(void)
int ms = 0;
ms++;
while (1);
return 0;
这是生成的程序集(对 PIC12f629 目标使用 sdcc
编译器)。如您所见,ms
变量已被“优化”。
_main:
; 2 exit points
_00113_DS_:
; .line 18; "main.c" while (1)
GOTO _00113_DS_
RETURN
; exit point of _main
另一方面,如果我们将变量声明为volatile
...
volatile int ms = 0;
ms++;
// etc.
保留相关说明:
_main:
; 2 exit points
; .line 16; "main.c" volatile int ms = 0;
CLRF _main_ms_1_5
CLRF (_main_ms_1_5 + 1)
; .line 19; "main.c" ms++;
INCF _main_ms_1_5,F
BTFSC STATUS,2
INCF (_main_ms_1_5 + 1),F
_00113_DS_:
; .line 21; "main.c" while (1)
GOTO _00113_DS_
RETURN
; exit point of _main
static
static
关键字的效果取决于声明变量的作用域。
#include
d 头文件)。
块作用域(例如,在函数内)- 变量在程序运行期间保存在内存中。 (对于一个函数,这意味着变量的值在函数的后续调用之间被保留。)
注意事项
正如 vlk 在评论中指出的那样,volatile
的另一个重要用途是访问外设寄存器(尽管在这种情况下您会使用指针)。
【讨论】:
很好的答案,但这不仅适用于中断,主要目的是定义映射到MCU具有外设和系统寄存器的地址的变量,例如GPIO,SYSTICK,RCC,......因为无法优化对这些寄存器的访问。 @naasif 如何检查标准或至少是一本好的 C 教科书? 好吧,@naasif,我会咬:port70.net/~nsz/c/c11/n1570.html 并且“我现在没有书” - 这就是问题所在。买一个。 大卫。它不会阻止任何优化。volatile
只保证变量在每次使用时都会从其存储位置读取,并在每次更改后存储。godbolt.org/g/hgv4hD
volatile
对于不受编译器完全控制的任何事物都是必不可少的。编译器不知道是否/何时/曾经执行过使用变量的 ISR,因此可能看不到访问其当前值的相关性。内存映射 IO 也不受编译器的控制:写入 IO 位置将对硬件产生影响,即使编译器认为这无关紧要,因为该值永远不会被读回。尽管软件没有写入该位置,但每次读取 IO 位置可能会产生不同的结果。这就是需要volatile
的原因。以上是关于C中__IO和静态关键字有啥用?的主要内容,如果未能解决你的问题,请参考以下文章