What is the difference between Register and volatile? when to use which one? what is the meaning of volatile register variable?
register int a;
volatile int a;
What is the difference between Register and volatile? when to use which one? what is the meaning of volatile register variable?
register int a;
volatile int a;
volatile means that the value of the variable can be changed by something which is not visible for the compiler. That means that the variable has to have a valid memory representation, it has to be read before any use, and stored if changed.
register - variable should be stored in the register if possible. The registers do not have the address so the operator & cannot be used on them. Ignored nowadays by most the compilers except very specific form:
avr gcc example: register unsigned char counter asm("r3");
which binds permanently the variable to the particular register. It decreases the register pool and makes optimisation more difficult
register unsigned char counter asm("r3");
Examples:
volatile int y;
int x8(volatile int x) // the x is read as many times as it is used
{
return x * x * x * x * x * x * x * x;
}
sub sp, sp, #8
str r0, [sp, #4]
ldr r3, [sp, #4]
ldr r1, [sp, #4]
ldr r2, [sp, #4]
mul r3, r1, r3
mul r3, r2, r3
ldr r2, [sp, #4]
ldr r0, [sp, #4]
mul r3, r2, r3
mul r3, r0, r3
ldr r2, [sp, #4]
ldr r0, [sp, #4]
mul r3, r2, r3
mul r3, r0, r3
ldr r0, [sp, #4]
mul r0, r3, r0
add sp, sp, #8
bx lr
int test(volatile int x) // parameter changed - stored
{
return x++;
}
sub sp, sp, #8
str r0, [sp, #4]
ldr r0, [sp, #4]
add r3, r0, #1
str r3, [sp, #4]
add sp, sp, #8
bx lr
int test2(void) same as above
{
return y++;
}
ldr r3, .L6
ldr r0, [r3]
add r2, r0, #1
str r2, [r3]
bx lr
volatile keyword should be used always when modification of variable can be asynchronous such as registers in CPU.
Example would be that you are using microcontroller and you are waiting flag when button is pressed. Then you are reading register like this:
uint8_t* reg = 0x12345678; //Register address
while (*reg & 0x02) { //Read register until 0 = button pressed
}
This can easily fail since compiler will check it once and later will ignore value and you may end in infinite loop or you don't even get anything since CPU can cache value of reg because it assumes noone can modify value where it points to.
If you do this:
volatile uint8_t* reg = 0x12345678; //Register address
while (*reg & 0x02) { //Read register until 0 = button pressed
}
You force compiler to do read instruction from actual memory before it uses content of variable. There is no cache in this case.
register keyword is just a hint for compiler that it should put variable to CPU register, but this is not always the case and some compilers ignore this keyword. It is implementation defined.