C standard compiler ko assume karne deta hai ki sirf wahi cheezein memory change karti hain jo operations tumhare translation unit mein visible hain. Usi assumption ke under woh teen optimizations karta hai jo hardware code ko tod deti hain:
Caching in registers — value ko CPU register mein rakho, RAM dobara read karne ki jagah.
Dead-store elimination — agar tum koi value likhte ho aur kabhi read nahi karte, toh woh write "dead" hai, toh delete karo.
Reordering — loads/stores ko idhar-udhar move karo jab tak single-threaded result "waise hi lagta" ho.
Lekin teen cheezein memory ko compiler ki knowledge ke bahar change karti hain:
Change ka source
Example
Memory-mapped hardware register
UART status bit flip hoti hai jab ek byte aata hai
ISR (interrupt service routine)
timer ISR tick_ready = 1 set karta hai
Doosra thread / DMA
DMA controller ek buffer mein write karta hai
Inke liye, compiler ki assumption galat hai, isliye uski optimizations wrong code produce karti hain. volatile us variable ke liye assumption ko hata deta hai.
Recall Feynman: ek 12-saal ke bacche ko explain karo
Socho tum ek scoreboard dekh rahe ho, lekin tum lazy ho, toh tum ek baar dekho, "0–0" yaad karo, phir bina upar dekhe "0–0" kehte rehte ho. Agar goal score hota hai, tum purana score kehte rahoge — tumne dekha hi nahi! volatile tumhara woh dost hai jo tumhe poke karta hai: "Hey, har baar ACTUALLY scoreboard dekho, score tab bhi change ho sakta hai jab tum nahi dekh rahe." Computers ke liye, "scoreboard" ek hardware chip ya button hai, aur lazy watcher compiler hai jo time bachane ki koshish kar raha hai.
Variable kisi bhi waqt, visible code action ke bina, change ho sakta hai, isliye har read/write ek real memory access honi chahiye aur optimize away ya reorder nahi honi chahiye.
Naam bolo teen optimizations jo volatile ek variable ke liye disable karta hai.
Value ko register mein cache karna, dead-store elimination, aur uske accesses ki reordering.
while(flag==0){} volatile ke bina forever loop kyun karta hai jab ISR flag set karta hai?
Compiler flag ko ek baar register mein read karta hai aur us cached copy pe loop karta hai; ISR sirf memory update karta hai, jise kabhi re-read nahi kiya jaata.
Kya volatilecount++ ke liye atomicity guarantee karta hai?
Nahi. Har access real memory access hoti hai lekin count++ abhi bhi load-modify-store hai aur interruptible hai; atomicity ke liye _Atomic/mutex use karo.
volatile int *p parse karo.
p ek volatile int ka pointer hai — pointed-to data volatile hai (har baar *p re-read karo). Hardware registers ke liye usual choice.
int * volatile p parse karo.
p khud volatile hai (pointer volatile memory mein rehta hai); jis data ki taraf yeh point karta hai woh ordinary hai.
const volatile ka ek register ke liye kya matlab hai?
Ek read-only hardware register: tumhara code ise kabhi nahi likhta (const) lekin hardware ise change karta hai (volatile), isliye phir bhi har access pe re-read karo.
Optimization band karna volatile ka bura substitute kyun hai?
Yeh sirf accidentally re-reads rakhta hai, fragile hai, higher -O levels pe toot ta hai, aur poore program ko slow karta hai; volatile har optimization level pe sahi hai.
FIFO ke do reads a=*DATA; b=*DATA; volatile kyun use karna chahiye?
Volatile ke bina compiler "redundant" doosra read remove kar deta hai (b=a), agla FIFO word khote hue, kyunki FIFO padhne ka ek side effect hota hai.