5.5.19 · D2 · HinglishEmbedded Systems & Real-Time Software

Visual walkthroughMISRA C — rules for safety-critical C code

2,489 words11 min read↑ Read in English

5.5.19 · D2 · Coding › Embedded Systems & Real-Time Software › MISRA C — rules for safety-critical C code

Parent note ne kaha tha: "Bitwise ops sirf unsigned types pe use karo jahan bit pattern standardized ho." Yahi MISRA C ke type-safety rules ka central result hai. Lekin kyun ek signed number ka bit pattern dangerous hota hai? Yeh page poora argument ground up se rebuild karta hai — "ek bit kya hoti hai" se lekar "(-1) >> 1 ek landmine kyun hai" tak — ek ek picture ke saath.

Hum har symbol use karne se pehle usse earn karenge. Agar tumne kabhi koi bit, shift, ya two's complement nahi dekha, toh line one se shuru karo aur theek rahoge.

Prerequisites jo hum link karenge lekin assume nahi: Embedded C Best Practices, Memory Safety, Static Analysis Tools. Parent: MISRA C parent (Hinglish).


Step 1 — Ek bit kya hoti hai, aur "bit pattern" kya hota hai?

KYA. Ek computer har number ko chhoti chhoti switches ki ek row mein store karta hai. Har switch ya toh off hoti hai (hum likhte hain 0) ya on (hum likhte hain 1). Ek switch = ek bit. Inhi switches ki ek fixed-width row — maano 8 — ek bit pattern hai.

KYU. Pehle "bits shift karna" ya "sign bit" ki baat karne se pehle, hume switches ki row literally dekhni chahiye. Aage ke har step mein bas yahi switches idhar udhar move ho rahi hain.

PICTURE. Neeche ek 8-bit row hai. Har cell ek bit hai. Number 13 yahan pattern 00001101 ke roop mein rehta hai.

Figure — MISRA C — rules for safety-critical C code

Row ko ordinary base-10 ki tarah padhna, lekin base-2 mein:

  • Har bit ke neeche label uska place value hai (do ki power).
  • Jahan bhi 1 baitha ho, unke place values add karo: . Yahi number hai.

Step 2 — Shift operator >> asliyat mein karta kya hai?

KYA. Operator >> (kaho "right shift") bits ki poori row leke har bit ko ek position daayein slide karta hai. Jo bits daayein edge se gir jaayein wo gaayab ho jaati hain. Khaali jagah bharne ke liye baayein ek naya bit aana chahiye.

KYU. MISRA Rule 10.1 << aur >> (aur &, |, ^) ke baare mein hai. Yeh judge karne ke liye ki rule rakhne layak hai ya nahi, hume dekhna chahiye ek shift row ke saath exactly kya karta hai — khaas kar khaali baayein slot mein kya aata hai, kyunki danger wahi chhupa hai.

PICTURE. Dekho 00001101 (=13) ek right shift mein 00000110 (=6) ban jaata hai. Sabse daayaan 1 gir jaata hai; ek 0 baayein se andar aata hai.

Figure — MISRA C — rules for safety-critical C code

Khaali-baayeen-slot ka sawaal — baayein se kya aata hai? — yahan easy tha: ek 0. Yeh dhyan mein rakho. Unsigned numbers ke liye answer hamesha 0 hota hai, aur yahi predictability poori rule ka point hai.


Step 3 — Negative numbers kahan rehte hain? (Two's complement, sign bit)

KYA. Bits ki row mein minus sign ke liye jagah nahi hoti. Toh negatives store karne ke liye, hardware ek convention use karta hai jise two's complement kehte hain: sabse baayaan bit ko ek negative place value ki tarah reinterpret kiya jaata hai. 8 bits mein, sabse baayaan bit ki value ki jagah hoti hai.

KYU. Rule 10.1 khaas taur par signed operands pe shifts forbid karta hai. Danger tab tak nahi dikhayi dega jab tak hum yeh nahi dekhte ki "signed" hone se usi bit-switches ki row ka matlab kaise badal jaata hai. Same switches, naya rulebook.

PICTURE. Wahi row, ab sabse baayaan place value pe flip ho gayi hai. Number wo pattern hai jisme har bit 1 ho.

Figure — MISRA C — rules for safety-critical C code

Check karo ki all-ones wakai hai:

  • Sabse baayaan 1 contribute karta hai (sign bit "on" ho gaya).
  • Baaki saat 1s contribute karte hain .
  • Total: . ✔

Toh pattern 11111111 hai number . Yeh yaad rakho; Step 5 mein yahi humara trap hai.


Step 4 — Raaste ka fork: baayeen slot bharne ke do tarike

KYA. Jab tum ek signed negative number ko right-shift karte ho, hardware designers ko incoming left bit ke liye ek choice face karni padti hai:

  • Logical shift: hamesha 0 andar laao.
  • Arithmetic shift: sign bit ki ek copy andar laao (agar number negative tha toh 1), taaki number negative hi rahe aur true division ki tarah behave kare.

KYU. Yahi poori rule ka exact hinge hai. C standard decide nahi karta ki signed types ke liye kaun sa hoga — yeh implementation-defined chhoda gaya hai, matlab compiler vendor pick karta hai. Do sahi compilers alag raah le sakte hain. Same source code, alag result.

PICTURE. -1 >> 1 ke liye dono forks side by side draw kiye. Baayaan fork (logical) 0 fill karta hai aur ek bahut bada positive number deta hai; daayaan fork (arithmetic) 1 fill karta hai aur waapas deta hai.

Figure — MISRA C — rules for safety-critical C code

Dono forks side by side:

  • Baayaan branch: upar 0 aa gaya, sign bit khatam ho gayi → result padhta hai (8-bit pe; 32-bit pe yeh bada ban jaata hai).
  • Daayaan branch: sign bit 1 ki copy aa gayi → result hi rehta hai.

Dono legal C hain. Ek braking system mein yeh ambiguity acceptable nahi hai.


Step 5 — Code mein landmine: (-1) >> 1

KYA. Hum sab kuch combine karte hain. Ek programmer likhta hai int result = (-1) >> 1; yeh expect karte hue ki " ka aadha, zero ki taraf round karke" — yaani , ya arithmetic hardware pe . Lekin ek aise compiler pe jo signed types ke logical shifts karta hai, unhe milta hai (sabse bada 32-bit signed value).

KYU. Yahi concrete disaster hai jo Rule 10.1 rokta hai. Ek value jo zero ke aas paas expect thi, achanak do arab se zyada ho jaati hai. Agar wo value kisi loop bound, memory index, ya timer ko feed kare, toh tumhare paas hang, out-of-bounds write (ek Memory Safety breach), ya ek Real-Time Operating Systems (RTOS) mein missed real-time deadline aa sakta hai.

PICTURE. Ek number line jo expected result dikhaye ( ya , origin ke paas) versus possible actual result (, bilkul daayein) — gap ko "silent catastrophe" label kiya gaya hai.

Figure — MISRA C — rules for safety-critical C code
int32_t x = -1;
int32_t r = x >> 1;   /* Rule 10.1 VIOLATION: signed operand of >> */
/* r is -1 on one compiler, 2147483647 on another. Both are legal C. */

Step 6 — MISRA ka fix: sirf unsigned operands shift karo

KYA. MISRA C:2012 Rule 10.1 essentially signed type ke operands pe bitwise aur shift operators forbid karta hai. Fix yeh hai: operand ko unsigned banao. Unsigned types ke liye C standard guarantee karta hai ki left slot 0 se fill hoga — logical shift — har compiler pe.

KYU. Ambiguity hatane se predictability restore hoti hai (ek core MISRA principle): wahi code har jagah wahi bit pattern deta hai. Ab value verifiable, testable hai, aur Formal Verification se reason karna safe hai.

PICTURE. Unsigned world: sirf ek fork exist karta hai. 11111111u (= 255) >> 1 hamesha → 01111111 (= 127). Koi choice nahi, koi vendor gamble nahi.

Figure — MISRA C — rules for safety-critical C code
uint32_t x = 0xFFFFFFFFU;   /* the unsigned value 4294967295 */
uint32_t r = x >> 1;        /* Rule 10.1 COMPLIANT */
/* r is 0x7FFFFFFF = 2147483647 on EVERY compiler. Deterministic. */

Dhyan do ki 0xFFFFFFFFU as unsigned matlab hai, aur >> 1 deta hai — ek defined answer, Step 5 ke signed trap se alag, bhale hi bit pattern similar lage.


Step 7 — Edge & degenerate cases (taaki kuch surprise na kare)

KYA. Chalo woh corners bhi dekh lete hain jo rule aur bhi protect karta hai.

KYU. Ek rule jo tum sirf "typical" case mein samajhte ho, boundaries pe bite karta hai. MISRA ki value yeh hai ki yeh sab ko uniformly cover karta hai signed operands ko outright ban karke.

PICTURE. Corner cases ki ek chhoti table, har ek ke liye "signed = ambiguous / unsigned = defined" verdict ke saath.

Figure — MISRA C — rules for safety-critical C code
Expression Signed operand (banned) Unsigned operand (compliant)
0 >> 1 Defined () lekin uniformity ke liye phir bhi banned , defined
x >> 0 (zero shift) No-op, lekin signedness phir bhi check hota hai , defined
x >> 32 (width shift) Undefined behaviour — shift width Phir bhi undefined — Rule 12.2 ise alag ban karta hai
-1 >> 1 (negative) The trap: ya n/a (pehle unsigned banao)
x << 1 bade x pe Sign bit mein/se overflow ho sakta hai → UB modulo wrap karta hai, defined

Ek-picture summary

Upar ki sab kuch ek diagram mein collapse hoti hai: wahi 8-bit row, ek baar right-shifted, signedness pe fork karti hai — unsigned hamesha safe (ek deterministic path), signed vendor gamble mein branching.

Figure — MISRA C — rules for safety-critical C code
Recall Feynman retelling — simple words mein khud se bolo

Ek computer mein ek number bas on/off switches ki ek row hota hai. Jab tum "shift right" karte ho, tum har switch ko ek seat daayein slide karte ho; koi end se gir jaata hai, aur ek naya switch baayein aata hai. Ek hi sawaal matter karta hai: woh naya baayaan switch kya hai? Ek plain, kabhi-negative-nahi number ke liye answer hamesha "off" hota hai — ek 0 — aur sab agree karte hain, toh shifting bas number ko aadha kar deta hai, har jagah, hamesha.

Lekin negative numbers ek trick se store hote hain: sabse baayaan switch secretly "minus bahut bada amount" ka matlab hota hai. Ab jab tum right shift karte ho, machine ke paas naye baayeen switch ke liye ek choice hoti hai — ek plain 0 andar laao, ya purane sign switch ko copy karo taaki number negative rahe. C language signed numbers ke liye choose karne se inkaar karta hai, toh yeh har compiler ko decide karne deta hai. Isliye (-1) >> 1 ek machine pe aur doosri pe do arab se zyada ho sakta hai — bina kisi warning ke.

MISRA Rule 10.1 choice hata ke temptation hatata hai: sirf unsigned numbers shift karo, jahan language promise karti hai ki naya switch har compiler pe 0 hoga. Ek rule, aur ambiguity khatam — tumhara code har jagah same matlab rakhta hai, jo exactly woh hai jo ek brake controller ko chahiye.

Recall Quick self-test

Jab tum ek unsigned value right-shift karte ho, khaali baayeen slot mein kya aata hai? ::: Hamesha ek 0 (logical shift), har compiler pe C standard guarantee karta hai. (-1) >> 1 dangerous kyun hai? ::: Signed shift ka fill bit implementation-defined hai, toh result compiler ke hisaab se (arithmetic) ya ek bahut bada positive number (logical) ho sakta hai. Kaun sa MISRA C:2012 rule essentially signed operands pe bitwise/shift ops ban karta hai? ::: Rule 10.1 (Required). Kya signed zero pe 0 >> 1 allowed hai? ::: Nahi — rule operand ki type judge karta hai, uski value nahi, toh signed zero phir bhi violation hai (yeh rule automatically decidable rakhta hai). Width se zyada shift karna kaun sa alag rule handle karta hai? ::: Rule 12.2 (shift count operand ki width se kam hona chahiye; warna yeh undefined behaviour hai).