volatile is a pre-defined keyword that is used to specify that the value in the variable may change at any time during the program execution. It prevents the compiler from optimizing the instructions.

Syntax:  <type-qualifier> <Datatype> <identifier>

Example: volatile int a;

To understand the concept of volatility in a precise manner, we need to know about the optimization levels in the GCC compilation. GCC compiler offers various optimization flags to optimize the program. They are O, O0, O1, O2, O3,  -Ofast, -Og, -Os e.t.c.

### #1 An example program using volatile type qualifier:

#include <stdio.h>
void main()
{
volatile int indicator = 0;
while(indicator == 0){
}
}

Use the below command to apply level 1 - Optimization (O1) while compiling the program.

gcc -O1 program.c -o executable

Use the below command to decompile the assembly instructions using Objdump. Learn how to use Objdump by using the "man page" i.e. use the command "man objdump".

objdump -d executable

Assembly instructions:

000000000000066a <main>:
66a:   53						push   %rbx
66b:   48 83 ec 10				sub    $0x10,%rsp 66f: c7 44 24 0c 00 00 00 movl$0x0,0xc(%rsp)
676:   00
677:   8b 44 24 0c				mov    0xc(%rsp),%eax
67b:   85 c0					test   %eax,%eax
67d:   75 21					jne    6a0 <main+0x36>
67f:   48 8d 1d ae 00 00 00	lea    0xae(%rip),%rbx        # 734 <_IO_stdin_used+0x4>
686:   48 89 de				mov    %rbx,%rsi
689:   bf 01 00 00 00			mov    $0x1,%edi 68e: b8 00 00 00 00 mov$0x0,%eax
693:   e8 a8 fe ff ff			callq  540 <__printf_chk@plt>
698:   8b 44 24 0c				mov    0xc(%rsp),%eax
69c:   85 c0					test   %eax,%eax
69e:   74 e6					je     686 <main+0x1c>
6a0:   48 83 c4 10				add    $0x10,%rsp 6a4: 5b pop %rbx 6a5: c3 retq 6a6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 6ad: 00 00 00 Explanation: At 66f, 0 is moving to 12 bytes above w.r.t to the stack pointer i.e. initializing the indicator variable with 0 (relative addressing mode). At 677 the value is again fetching back to register for the comparison at 67b i.e. in the while loop. If the result is false then 67d will be executed else 67f will be executed. Now, If you closely observe the instructions 66f, 677, 67b, 698, 69c always the value is directly fetching from the memory to register i.e from (0xc(%rsp)) to %eax for the comparison in the while loop. Due to this, we always have an updated value even though if this value is changed by some other thread in the program execution. #2 An example program without using volatile type qualifier: #include <stdio.h> void main() { int indicator = 0; while(indicator == 0){ printf("Downloading Data ....."); } } Command to compile: gcc -O1 program.c -o program Decompile the assembly: objdump -d program Assembly instructions: 000000000000066a <main>: 66a: 53 push %rbx 66b: 48 8d 1d a2 00 00 00 lea 0xa2(%rip),%rbx # 714 <_IO_stdin_used+0x4> 672: 48 89 de mov %rbx,%rsi 675: bf 01 00 00 00 mov$0x1,%edi
67a:   b8 00 00 00 00			mov    \$0x0,%eax
67f:   e8 bc fe ff ff			callq  540 <__printf_chk@plt>
684:   eb ec					jmp    672 <main+0x8>
686:   66 2e 0f 1f 84 00 00	nopw   %cs:0x0(%rax,%rax,1)
68d:   00 00 00

Explanation:

If you observe, there is no comparison instruction in the above assembly program. If we think from the compiler's perspective, the value of the 'indicator'  will always be a '0' because it is not being changed in the while loop & there is no point in comparing it again and again with '0'. Due to this, the compiler optimizes this instruction and prints the message continuously onto the screen without comparing.

But this creates a hell-like situation when an object is shared between multiple concurrent processes. Because any process can change the value at any time.\