[英]Difference between const & const volatile
If we declare a variable as volatile
every time the fresh value is updated如果每次更新新值时我们都将变量声明为
volatile
If we declare a variable as const
then the value of that variable will not be changed如果我们将一个变量声明为
const
那么该变量的值将不会改变
Then const volatile int temp;
然后
const volatile int temp;
What is the use of declaring the variable temp
as above?如上所述声明变量
temp
有什么用?
What happens if we declare as const int temp
?如果我们声明为
const int temp
会发生什么?
An object marked as const volatile
will not be permitted to be changed by the code (an error will be raised due to the const
qualifier) - at least through that particular name/pointer.代码不允许更改标记为
const volatile
的对象(由于const
限定符将引发错误)-至少通过该特定名称/指针。
The volatile
part of the qualifier means that the compiler cannot optimize or reorder access to the object.限定符的
volatile
部分意味着编译器无法优化或重新排序对对象的访问。
In an embedded system, this is typically used to access hardware registers that can be read and are updated by the hardware, but make no sense to write to (or might be an error to write to).在嵌入式系统中,这通常用于访问可由硬件读取和更新的硬件寄存器,但写入没有意义(或者可能是写入错误)。
An example might be the status register for a serial port.一个例子可能是串行端口的状态寄存器。 Various bits will indicate if a character is waiting to be read or if the transmit register is ready to accept a new character (ie., - it's empty).
各种位将指示字符是否正在等待读取或发送寄存器是否已准备好接受新字符(即 - 它是空的)。 Each read of this status register could result in a different value depending on what else has occurred in the serial port hardware.
根据串行端口硬件中发生的其他情况,对该状态寄存器的每次读取都可能导致不同的值。
It makes no sense to write to the status register (depending on the particular hardware spec), but you need to make sure that each read of the register results in an actual read of the hardware - using a cached value from a previous read won't tell you about changes in the hardware state.写入状态寄存器是没有意义的(取决于特定的硬件规格),但是您需要确保每次读取寄存器都会导致对硬件的实际读取 - 使用先前读取的缓存值将不会' t 告诉您硬件状态的变化。
A quick example:一个简单的例子:
unsigned int const volatile *status_reg; // assume these are assigned to point to the
unsigned char const volatile *recv_reg; // correct hardware addresses
#define UART_CHAR_READY 0x00000001
int get_next_char()
{
while ((*status_reg & UART_CHAR_READY) == 0) {
// do nothing but spin
}
return *recv_reg;
}
If these pointers were not marked as being volatile
, a couple problems might occur:如果这些指针没有被标记为
volatile
,可能会出现一些问题:
*recv_reg
is changed by the loop, there's no reason it can't be read before entering the loop.*recv_reg
被循环更改,没有理由在进入循环之前无法读取它。 The volatile
qualifiers ensures that these optimizations are not performed by the compiler. volatile
限定符确保编译器不会执行这些优化。
volatile
will tell the compiler not to optimise code related the variable, usually when we know it can be changed from "outside", eg by another thread. volatile
会告诉编译器不要优化与变量相关的代码,通常是当我们知道它可以从“外部”更改时,例如通过另一个线程。const
will tell the compiler that it is forbidden for the program to modify the variable's value. const
会告诉编译器禁止程序修改变量的值。const volatile
is a very special thing you'll probably see used exactly 0 times in your life (tm). const volatile
是一个非常特别的东西,你可能会在你的生活中看到它使用了 0 次 (tm)。 As is to be expected, it means that the program cannot modify the variable's value, but the value can be modified from the outside, thus no optimisations will be performed on the variable.It is not because the variable is const that it may not have changed between two sequence points.并不是因为变量是常量,所以它在两个序列点之间可能没有改变。
Constness is a promise you make not to change the value, not that the value won't be changed. Constness 是你做出的不改变价值的承诺,而不是价值不会改变。
In C, const
and volatile
are type qualifiers and these two are independent.在 C 中,
const
和volatile
是类型限定符,这两个是独立的。
Basically, const
means that the value isn't modifiable by the program.基本上,
const
意味着该值不能被程序修改。
And volatile
means that the value is subject to sudden change (possibly from outside the program).而
volatile
意味着该值会发生突然变化(可能来自程序外部)。
In fact, the C Standard gives an example of a valid declaration which is both const
and volatile
.事实上,C 标准给出了一个既是
const
又是volatile
的有效声明的例子。 The example is:例子是:
extern const volatile int real_time_clock;
where real_time_clock
may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.其中
real_time_clock
可由硬件修改,但不能分配、递增或递减。
So we should already treat const
and volatile
separately.所以我们应该已经分别对待
const
和volatile
。 These type qualifiers can be applied to struct
, union
, enum
and typedef
as well.这些类型限定符也可以应用于
struct
、 union
、 enum
和typedef
。
I've needed to use this in an embedded application where some configuration variables are located in an area of flash memory that can be updated by a bootloader.我需要在嵌入式应用程序中使用它,其中一些配置变量位于闪存区域,可由引导加载程序更新。 These config variables are 'constant' during runtime, but without the volatile qualifier the compiler would optimise something like this...
这些配置变量在运行时是“常量”,但如果没有 volatile 限定符,编译器会优化这样的东西......
cantx.id = 0x10<<24 | CANID<<12 | 0;
...by precomputing the constant value and using an immediate assembly instruction, or loading the constant from a nearby location, so that any updates to the original CANID value in the config flash area would be ignored. ...通过预先计算常量值并使用立即汇编指令,或从附近位置加载常量,这样对配置闪存区域中原始 CANID 值的任何更新都将被忽略。 CANID has to be const volatile.
CANID 必须是 const 可变的。
const
means that the variable cannot be modified by the c code, not that it cannot change. const
表示变量不能被 c 代码修改,而不是它不能改变。 It means that no instruction can write to the variable, but its value might still change.这意味着没有指令可以写入变量,但它的值可能仍然会改变。
volatile
means that the variable may change at any time and thus no cached values might be used; volatile
意味着该变量可能随时更改,因此可能不会使用缓存值; each access to the variable has to be executed to its memory address.对变量的每次访问都必须执行到其内存地址。
Since the question is tagged "embedded" and supposing temp
is a user declared variable, not a hardware-related register (since these are usually handled in a separate .h file), consider:由于问题被标记为“嵌入式”并且假设
temp
是用户声明的变量,而不是与硬件相关的寄存器(因为这些通常在单独的 .h 文件中处理),请考虑:
An embedded processor which has both volatile read-write data memory (RAM) and non-volatile read-only data memory, for example FLASH memory in von-Neumann architecture, where data and program space share a common data and address bus.具有易失性读写数据存储器 (RAM) 和非易失性只读数据存储器的嵌入式处理器,例如冯诺依曼架构中的闪存,其中数据和程序空间共享公共数据和地址总线。
If you declare const temp
to have a value (at least if different from 0), the compiler will assign the variable to an address in FLASH space, because even if it were assigned to a RAM address, it still needs FLASH memory to store the initial value of the variable, making the RAM address a waste of space since all operations are read-only.如果你声明
const temp
有一个值(至少在不等于 0 的情况下),编译器会将该变量分配给 FLASH 空间中的一个地址,因为即使它被分配给一个 RAM 地址,它仍然需要 FLASH 存储器来存储变量的初始值,使 RAM 地址浪费空间,因为所有操作都是只读的。
In consequence:结果:
int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values may be used.是存储在 RAM 中的变量,在启动 (cstart) 时初始化为 0,可以使用缓存值。
const int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values may be used.是存储在(只读)FLASH 中的变量,在编译器时初始化为 0,可以使用缓存值。
volatile int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values will NOT be used.是存储在 RAM 中的变量,在启动 (cstart) 时初始化为 0,不会使用缓存值。
const volatile int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values will NOT be used是存储在(只读)FLASH 中的变量,在编译器时初始化为 0,不会使用缓存值
Here comes the usefull part:有用的部分来了:
Nowadays most Embedded processors have the ability to make changes to their read-only non-volatile memory by means of a special function module, in which case const int temp
can be changed at runtime, altought not directly.如今,大多数嵌入式处理器都能够通过特殊功能模块对其只读非易失性存储器进行更改,在这种情况
const int temp
可以在运行时更改const int temp
,而不是直接更改。 Said in another way, a function may modify the value at the address where temp
is stored.换句话说,函数可以修改存储
temp
的地址处的值。
A practical example would be to use temp
for the device serial number.一个实际的例子是使用
temp
作为设备序列号。 The first time the embedded processor runs, temp
will be equal to 0 (or the declared value) and a function can use this fact to run a test during production and if sucessfull, ask to be assigned a serial number and modify the value of temp
by means of a special function.嵌入式处理器第一次运行时,
temp
将等于 0(或声明的值),一个函数可以使用这个事实在生产过程中运行测试,如果成功,要求分配一个序列号并修改temp
的值通过特殊功能。 Some processors have a special address range with OTP (one-time programmable) memory just for that.一些处理器有一个特殊的地址范围,带有 OTP(一次性可编程)内存。
But here comes the difference:但不同之处在于:
If const int temp
is a modifiable ID instead of a one-time-programmable serial number and is NOT declared volatile
, a cached value might be used untill the next boot, meaning the new ID might not be valid untill the next reboot, or even worse, some functions might use the new value while other might use an older cached value untill reboot.如果
const int temp
是一个可修改的 ID 而不是一次性可编程的序列号,并且未声明为volatile
,则可能会使用缓存值直到下一次启动,这意味着新 ID 可能在下一次重新启动之前无效,甚至更糟糕的是,某些功能可能会使用新值,而其他功能可能会使用较旧的缓存值,直到重新启动。 If const int temp
IS declared voltaile
, the ID change will take effect immediately.如果
const int temp
IS 声明为voltaile
,则 ID 更改将立即生效。
You can use const
and volatile
together.您可以同时使用
const
和volatile
。 For example, if 0x30
is assumed to be the value of a port that is changed by external conditions only, the following declaration would prevent any possibility of accidental side effects:例如,如果假定
0x30
是仅由外部条件更改的端口值,则以下声明将防止任何意外副作用的可能性:
const volatile char *port = (const volatile char *)0x30;
This article discusses the scenarios where you want to combine const and volatile qualifiers.本文讨论了您想要组合 const 和 volatile 限定符的场景。
http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/ http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/
In simple terms, Value in 'const volatile' variable cannot be modified programmatically but can be modified by hardware.简单来说,'const volatile' 变量中的值不能以编程方式修改,但可以通过硬件修改。 Volatile here is to prevent any compiler optimisation.
Volatile 是为了防止任何编译器优化。
We use 'const' keyword for a variable when we don't want to the program to change it.当我们不想让程序改变它时,我们对变量使用“const”关键字。 Whereas when we declare a variable 'const volatile' we are telling the program not to change it and the compiler that this variable can be changed unexpectedly from input coming from the outside world.
而当我们声明一个变量“const volatile”时,我们是在告诉程序不要改变它,编译器可以从外部世界的输入中意外地改变这个变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.