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
?
10 Answers 10
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.
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:
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:
- the while loop test might read the status register only once, since the compiler could assume that whatever it pointed to would never change (there's nothing in the while loop test or loop itself that could change it). If you entered the function when there was no character waiting in UART hardware, you might end up in an infinite loop that never stopped even when a character was received.
- the read of the receive register could be moved by the compiler to before the while loop - again because there's nothing in the function that indicates that
*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.
-
5+1 for explanation. And I have a question: what about const volatile methods? If I have a class, which is accessed by many threads (although access is synchronized with mutex) does my const methods also have to be volatile (since some variable could be changed by other thread)Sasa– Sasa2012年08月08日 23:31:15 +00:00Commented Aug 8, 2012 at 23:31
-
A simple question: why
const volatile
objects can never be placed in read-only memory? See C11, footnote 132.pmor– pmor2022年09月20日 20:04:42 +00:00Commented Sep 20, 2022 at 20:04 -
@pmor: The semantics of volatile-qualified objects are implementation-defined. The Standard gives implementations blanket permission to interpret a
const
qualifier on an object that isn'tvolatile
as an invitation to place the object in read-only storage, with no obligation to document such treatment. An implementation could specify that the semantics ofvolatile
objects vary depending upon whether they areconst
, but if an implementation doesn't document thatconst
affects the behavior ofvolatile
objects, thenconst volatile
objects must behave likevolatile
ones.supercat– supercat2023年06月06日 14:55:20 +00:00Commented Jun 6, 2023 at 14:55 -
1@supercat Since "An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects" AND if
const volatile
object is placed in read-only memory, then one may ask: "how this object can be modified in ways unknown to the implementation if it is placed in read-only memory?". However, such a modification is outside of C. Perhaps OS (if any) temporarily removes "read only" attribute, etc. Have a look: reviews.llvm.org/D131012.pmor– pmor2023年06月07日 11:07:35 +00:00Commented Jun 7, 2023 at 11:07 -
@pmor: I see nothing in the text that would forbid an implementation from treating volatile-qualified objects in any manner they see fit, provided they document it. For clang to refuse to place objects there because the Standard supposedly forbids it would be a gross abuse of the Standard, though in line with what I've come to expect from the maintainers of clang.supercat– supercat2023年06月07日 14:58:57 +00:00Commented Jun 7, 2023 at 14:58
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.
-
14I'd have thought that
volatile
variables are usually what happens when you start messing with hardware, not with other threads. Where I've seenconst volatile
used is in things like memory-mapped status registers or the like.JUST MY correct OPINION– JUST MY correct OPINION2011年01月04日 12:33:18 +00:00Commented Jan 4, 2011 at 12:33 -
2Of course, you're absolutely right, multithreading is just one example, but not the only one :).mingos– mingos2011年01月04日 15:16:07 +00:00Commented Jan 4, 2011 at 15:16
-
34If you work with embedded systems you will see this very often.Daniel Grillo– Daniel Grillo2013年10月11日 12:04:16 +00:00Commented Oct 11, 2013 at 12:04
-
1Its not actually that special, I see it all the time in embedded workYvan Pearson– Yvan Pearson2022年07月08日 22:31:09 +00:00Commented Jul 8, 2022 at 22:31
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.
-
10Plus one for pointing out that
const
data is not "constant".Bogdan Alexandru– Bogdan Alexandru2015年01月26日 07:47:07 +00:00Commented Jan 26, 2015 at 7:47 -
Is there any type of qualifier that completely prevents modification of a variable, both by program and external?Abdel Aleem– Abdel Aleem2024年02月05日 09:16:03 +00:00Commented Feb 5, 2024 at 9:16
In C, const
and volatile
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
and 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.
So we should already treat const
and volatile
separately. These type qualifiers can be applied to struct
, union
, enum
and typedef
as well.
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...
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 has to be const volatile.
You can use const
and volatile
together. 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:
const volatile char *port = (const volatile char *)0x30;
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 used
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. Said in another way, a function may modify the value at the address where temp
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 of temp
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 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.
If const int temp
IS declared voltaile
, the ID change will take effect immediately.
-
Another that you might add to your list is
const volatile int * const p;
which means thatp
is aconst
pointer so can't be changed and it points to a data item that isconst volatile
so you can't change that data item through the pointerp
either.Richard Chambers– Richard Chambers2024年12月20日 18:02:48 +00:00Commented Dec 20, 2024 at 18:02
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.
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.
Example:
const volatile uint16_t variable;
This is a possible declaration of a 16-bit read-only register.
The const
keyword says the program cannot change that memory location.
The volatile
keyword says that location might change at any moment, independently of the program course.
So, their combination is usual for read-only registers, for example a status register. Because the software cannot change the content of that register we use const
, but the hardware might change its value at any time, independently on software, so we use volatile
.
Moreover, the volatile
keyword instructs the compiler to not optimize and not make any shadow copy of that memory location.
const volatile int temp;
at block scope (i.e. inside{ }
), it has no use there.