const表示该变量不能被c代码修改,并不是不能改变。这意味着没有指令可以写入变量,但它的值可能仍然会改变。
volatile 表示该变量可能随时更改,因此可能不会使用缓存值;对变量的每次访问都必须执行到它的内存地址。
由于问题被标记为“嵌入”并且假设 temp 是用户声明的变量,而不是与硬件相关的寄存器(因为这些通常在单独的 .h 文件中处理),请考虑:
同时具有易失性读写数据存储器 (RAM) 和非易失性只读数据存储器的嵌入式处理器,例如冯诺依曼架构中的 FLASH 存储器,其中数据和程序空间共享公共数据和地址总线.
如果你声明const temp有一个值(至少如果不为0),编译器会将变量分配给FLASH空间中的地址,因为即使分配给RAM地址,它仍然需要FLASH内存来存储变量的初始值,由于所有操作都是只读的,因此使RAM地址浪费空间。
结果:
int temp;是存储在RAM中的变量,启动时初始化为0(cstart),可以使用缓存值。
const int temp;是存储在(只读)FLASH中的变量,编译时初始化为0,可以使用缓存值。
volatile int temp; 是存储在 RAM 中的变量,在启动(cstart)时初始化为 0,不会使用缓存的值。
const volatile int temp;是存储在(只读)FLASH中的变量,编译时初始化为0,缓存值不会被使用
有用的部分来了:
如今,大多数嵌入式处理器都能够通过特殊功能模块对其只读非易失性存储器进行更改,在这种情况下,const int temp 可以在运行时更改,但不能直接更改。换句话说,一个函数可以修改temp所在地址的值。
一个实际的例子是使用temp 作为设备序列号。嵌入式处理器第一次运行时,temp 将等于 0(或声明的值),并且函数可以使用此事实在生产期间运行测试,如果成功,则要求分配序列号并修改值temp 的特殊功能。一些处理器有一个特殊的地址范围,带有 OTP(一次性可编程)内存,仅用于此目的。
但这里有区别:
如果const int temp 是可修改 ID 而不是一次性可编程序列号并且未声明为 volatile,则可能会使用缓存值直到下一次启动,这意味着新 ID 可能直到下次重新启动,或者更糟糕的是,某些函数可能会使用新值,而其他函数可能会使用旧的缓存值,直到重新启动。
如果const int temp被声明为voltaile,则ID更改将立即生效。