const 和 const 之间的区别常量易失性
如果每次更新新值时我们都将变量声明为易失性
如果我们将变量声明为 const 那么该变量的值将不会改变
然后 const volatile int temp;
如上声明变量 temp
有什么用?
如果我们声明为 const int temp 会发生什么?
If we declare a variable as volatile
every time the fresh value is updated
If we declare a variable as const
then the value of that variable will not be changed
Then const volatile int temp;
What is the use of declaring the variable temp
as above?
What happens if we declare as const int temp
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
标记为
const volatile
的对象将不允许被代码更改(由于const
限定符将引发错误) - 至少通过该特定名称/指针。限定符的
易失性
部分意味着编译器无法优化或重新排序对对象的访问。在嵌入式系统中,这通常用于访问可由硬件读取和更新的硬件寄存器,但写入没有意义(或者写入可能会出错)。
串行端口的状态寄存器就是一个例子。各个位将指示字符是否正在等待读取,或者发送寄存器是否准备好接受新字符(即,它为空)。每次读取该状态寄存器都可能产生不同的值,具体取决于串行端口硬件中发生的其他情况。
写入状态寄存器是没有意义的(取决于特定的硬件规格),但您需要确保每次读取寄存器都会导致对硬件的实际读取 - 使用先前读取的缓存值不会'不会告诉您硬件状态的变化。
一个简单的例子:
如果这些指针没有被标记为易失性,则可能会出现几个问题:
*recv_reg
被循环更改,所以没有理由不能在进入循环之前读取。易失性
限定符确保编译器不会执行这些优化。An object marked as
const volatile
will not be permitted to be changed by the code (an error will be raised due to theconst
qualifier) - at least through that particular name/pointer.The
volatile
part of the qualifier means that the compiler cannot optimize or reorder access to the object.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.
A quick example:
If these pointers were not marked as being
volatile
, a couple problems might occur:*recv_reg
is changed by the loop, there's no reason it can't be read before entering the loop.The
volatile
qualifiers ensures that these optimizations are not performed by the compiler.易失性
会告诉编译器不要优化与变量相关的代码,通常是当我们知道它可以从“外部”(例如另一个线程)更改时。const
会告诉编译器禁止程序修改变量的值。const volatile
是一个非常特殊的东西,你可能会在你的生活中看到它被使用了 0 次(tm)。正如所料,这意味着程序无法修改变量的值,但可以从外部修改该值,因此不会对变量执行优化。volatile
will tell the compiler not to optimise code related the variable, usually when we know it can be changed from "outside", e.g. by another thread.const
will tell the compiler that it is forbidden for the program to modify the variable's value.const volatile
is a very special thing you'll probably see used exactly 0 times in your life (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.这并不是因为该变量是 const,所以它在两个序列点之间可能没有改变。
常量是你做出的不改变值的承诺,而不是值不会改变。
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.
在 C 中,
const
和volatile
是类型限定符,并且这两个是独立的。基本上,
const
意味着该值不能由程序修改。易失性意味着该值会突然发生变化(可能来自程序外部)。
事实上,C 标准给出了一个有效声明的示例,该声明既是 const 又是 volatile。示例为:
extern const volatile int real_time_clock;
,其中
real_time_clock
可以由硬件修改,但不能分配、递增或递减。所以我们应该已经分别对待
const
和volatile
了。这些类型限定符也可以应用于struct
、union
、enum
和typedef
。In C,
const
andvolatile
are type qualifiers and these two are independent.Basically,
const
means that the value isn’t modifiable by the program.And
volatile
means that the value is subject to sudden change (possibly from outside the program).In fact, the C Standard gives an example of a valid declaration which is both
const
andvolatile
. 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.So we should already treat
const
andvolatile
separately. These type qualifiers can be applied tostruct
,union
,enum
andtypedef
as well.我需要在嵌入式应用程序中使用它,其中一些配置变量位于可由引导加载程序更新的闪存区域中。这些配置变量在运行时是“常量”,但是如果没有 volatile 限定符,编译器会优化这样的东西...
...通过预先计算常量值并使用立即汇编指令,或者从附近的位置加载常量,所以对配置闪存区域中原始 CANID 值的任何更新都将被忽略。 CANID 必须是常量易失性的。
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...
...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 has to be const volatile.
您可以同时使用
const
和易失性
。例如,如果0x30
被假定为端口的值仅由外部条件改变,以下声明将防止任何可能性
意外副作用:
You can use
const
andvolatile
together. For example, if0x30
is assumed to be the value of a portthat is changed by external conditions only, the following declaration would prevent any possibility
of accidental side effects:
const
表示该变量不能被c代码修改,而不是不能改变。这意味着没有指令可以写入该变量,但它的值仍然可能会改变。易失性
意味着变量可能随时改变,因此不能使用缓存的值;对变量的每次访问都必须执行到其内存地址。由于问题被标记为“嵌入式”,并且假设 temp 是用户声明的变量,而不是与硬件相关的寄存器(因为这些寄存器通常在单独的 .h 文件中处理),请考虑:
一个嵌入式处理器,它既有易失性读写数据存储器(RAM),也有非易失性只读数据存储器,例如冯诺依曼架构中的FLASH存储器,其中数据和程序空间共享公共数据和地址总线。
如果你声明const temp有一个值(至少不等于0),编译器会将该变量分配给FLASH空间中的一个地址,因为即使它被分配给一个RAM地址,它仍然需要FLASH存储器来存储变量的初始值,这使得RAM地址浪费空间,因为所有操作都是只读的。
因此:
int temp;
是一个存储在 RAM 中的变量,在启动 (cstart) 时初始化为 0,可以使用缓存的值。const int temp;
是存储在(只读)FLASH 中的变量,在编译时初始化为 0,可以使用缓存的值。volatile int temp;
是一个存储在RAM中的变量,在启动(cstart)时初始化为0,缓存的值将不会被使用。const volatile int temp;
是一个存储在(只读)FLASH 中的变量,在编译时初始化为 0,不会使用缓存的值这里是有用的部分:
现在大多数嵌入式处理器都有能力通过特殊功能模块对其只读非易失性存储器进行更改,在这种情况下,
const int temp
可以在运行时更改,但不能直接更改。换句话说,函数可以修改存储temp
的地址处的值。一个实际的示例是使用
temp
作为设备序列号。嵌入式处理器第一次运行时,temp
将等于 0(或声明值),函数可以使用此事实在生产期间运行测试,如果成功,则要求分配一个序列号number 并通过特殊函数修改temp
的值。一些处理器具有特殊的地址范围和 OTP(一次性可编程)内存。但区别在于:
如果
const int temp
是一个可修改的 ID,而不是一次性可编程序列号,并且未声明易失性
,则可能会使用缓存值直到下次启动,这意味着新的 ID 可能直到下次重新启动才有效,或者更糟糕的是,某些功能可能会使用新值,而其他功能可能会使用旧的缓存值,直到重新启动。如果
const int temp
声明为voltaile
,则 ID 更改将立即生效。const
means that the variable cannot be modified by the c code, not that it cannot change. 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; 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: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.
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.In consequence:
int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values may be used.const int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values may be used.volatile int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values will NOT be used.const volatile int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values will NOT be usedHere 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. Said in another way, a function may modify the value at the address wheretemp
is stored.A practical example would be to use
temp
for the device serial number. 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 oftemp
by means of a special function. Some processors have a special address range with OTP (one-time programmable) memory just for that.But here comes the difference:
If
const int temp
is a modifiable ID instead of a one-time-programmable serial number and is NOT declaredvolatile
, 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.If
const int temp
IS declaredvoltaile
, the ID change will take effect immediately.简单来说,
“const volatile”变量中的值不能以编程方式修改,但可以通过硬件修改。这里的易失性是为了防止任何编译器优化。
In simple terms,
Value in 'const volatile' variable cannot be modified programmatically but can be modified by hardware. Volatile here is to prevent any compiler optimisation.
当我们不希望程序更改变量时,我们对变量使用“const”关键字。然而,当我们声明变量“const volatile”时,我们是在告诉程序不要更改它,并且告诉编译器该变量可能会因来自外部世界的输入而被意外更改。
We use 'const' keyword for a variable when we don't want to the program to change it. 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.