5.1.31 · D5 · HinglishC Programming

Question bankCompile-time assertions — static_assert

1,505 words7 min read↑ Read in English

5.1.31 · D5 · Coding › C Programming › Compile-time assertions — static_assert

Shuru karne se pehle, woh ek sentence yaad karo jo in mein se zyada problems solve kar deta hai: static_assert ko compiler evaluate karta hai, isliye iska condition ek constant expression hona chahiye — ek aisi value jo program run kiye bina poori tarah se known ho.


True ya false — justify karo

C11 mein tum static_assert mein message string chhod sakte ho.
False. C11/C17 mein message mandatory hai; sirf C23 (dekho C11 vs C23 language features) ne ise optional banaya. C11 ke under ise bhoolna ek hard compile error hai.
Ek passing static_assert ek tiny runtime check add karta hai jise CPU jaldi skip kar leta hai.
False. Ek passing assertion zero machine code emit karta hai — runtime par skip karne ke liye kuch hota hi nahi. Compiler ne translation ke dauran value already compute kar li hoti hai.
static_assert(1 == 1); aur assert(1 == 1); basically ek hi cheez hain.
False. static_assert compile time par fire karta hai aur constant chahiye; assert (<assert.h> se) run time par fire karta hai aur variables inspect kar sakta hai. Ye dono program ki life ke alag alag phases mein rehte hain.
C11 mein static_assert koi bhi header include kiye bina likh sakte hain.
False, friendly name ke liye — C11 mein static_assert ek macro hai <assert.h> mein. Raw keyword _Static_assert ko koi header nahi chahiye.
#error check kar sakta hai ki sizeof(int) == 4 hai ya nahi.
False. #error preprocessor mein run hota hai, jiske paas koi type information nahi hoti — woh sizeof evaluate nahi kar sakta. Sirf compiler (static_assert ke zariye) type sizes jaanta hai.
static_assert(sizeof(int) == 4); C23 mein theek se compile hoga.
True. C23 mein static_assert ek real keyword hai aur message optional hai, isliye akela condition legal hai. C11 ke under wahi line message na hone ki wajah se fail hoti hai.
assert ko NDEBUG se compile out karna static_assert ko bhi disable kar deta hai.
False. NDEBUG sirf runtime assert ko silence karta hai. static_assert unaffected rehta hai — yeh koi debugging aid nahi hai jise tum band kar sako, yeh ek build gate hai.
Ek function ke andar false static_assert jise tum kabhi call nahi karte, harmless hai.
False. Compiler ise translation ke dauran evaluate karta hai, chahe enclosing function kabhi call ho ya reachable ho ya na ho — build phir bhi fail hoti hai.

Error dhundho

int n = read_config();
static_assert(n > 0, "n must be positive");

::: n ek runtime variable hai, isliye n > 0 ek constant expression nahi hai — yeh compile fail kar deta hai. Runtime data ke liye assert use karo; static_assert sirf compile-time-known values ke liye hai.

// C11 source, no includes
static_assert(sizeof(long) >= 4, "long too small");

::: C11 mein static_assert spelling ek macro hai — #include <assert.h> ke bina woh naam undefined hai. Fix: header include karo, ya raw keyword _Static_assert likho.

#define SIZE 100
#error (SIZE % 2 == 0) ? 0 : "SIZE must be even"

::: #error expressions evaluate nahi karta — uske baad jo bhi hota hai woh sirf text hai jo unconditionally print hota hai. Even size conditionally check karne ke liye tumhe #if SIZE % 2 != 0#error … chahiye, ya code mein static_assert.

static_assert(strlen("hi") == 2, "wrong");

::: strlen ek runtime function call hai, isliye argument ek constant expression nahi hai — yeh compile nahi hoga. Agar tumhe sach mein build time par chahiye toh sizeof("hi") - 1 use karo (ek compile-time constant, null terminator minus).

static_assert(get_flag() ? 1 : 0, "flag off");

::: C mein ek function call get_flag() kabhi constant expression nahi ho sakti, isliye yeh illegal hai. Constant conditions sirf literals, sizeof, enum values, aur #defined constants se bani honi chahiyein.

enum { A = 1, B = 2 };
static_assert(A + B, "sum is zero");   // meant to catch A+B == 0

::: Condition sirf value 3 hai, jo non-zero (true) hai, isliye yeh silently pass ho jaata hai aur kuch meaningful check nahi karta. Author comparison bhool gaya; unhe static_assert(A + B != 0, ...) chahiye tha.


Why questions

Condition constant kyun honi chahiye, sirf "koi bhi true expression" kyun nahi?
Kyunki compiler ko ise translation ke dauran evaluate karna hota hai, program run kiye bina — ek variable ki value compile time par abhi exist hi nahi karti, isliye compiler ke paas test karne ke liye kuch hota hi nahi.
static_assert ka runtime cost zero kyun hai jabki assert ka thoda cost hai?
static_assert compile time par poori tarah resolve ho jaata hai aur koi code produce nahi karta; assert ek actual runtime if-check-and-abort mein compile hota hai jo har baar us line ke run hone par execute hota hai (jab tak NDEBUG se remove na ho).
Usi cheez ke liye runtime check ke bajaaye static_assert(sizeof(int)==4) prefer kyun karein?
int ka size compile karte hi fix ho jaata hai — yeh kabhi per run ya per input vary nahi karta. Ek runtime check ek already-known truth ko re-verify karne mein cycles waste karega, aur ek broken binary ship ho sakti hai; compile-time check broken build ko produce karna hi impossible bana deta hai.
static_assert sizeof use kar sakta hai lekin #error nahi kar sakta, kyun?
sizeof ko types ki compiler knowledge chahiye; #error preprocessor mein kaam karta hai — ek earlier phase jo sirf text tokens manipulate karta hai aur types ya sizes ke baare mein kuch nahi jaanta.
static_assert(sizeof(names)/sizeof(names[0]) == COUNT) ek constant expression kyun hai?
Ek array ki total byte size aur element size dono compile time par fixed hoti hain, isliye unka quotient (element count) ek compile-time constant hai — compiler ise COUNT se bina kuch run kiye compare kar sakta hai.
File scope par (kisi bhi function ke bahar) static_assert rakhna kyun kaam karta hai?
static_assert ek declaration hai, isliye yeh wahan legal hai jahan koi bhi declaration ho sakti hai — file scope par, struct ke andar, ya function body ke andar. Ise koi surrounding statement ya executable context nahi chahiye.

Edge cases

static_assert(0, "always here"); — kya hota hai?
Condition constant zero (false) hai, isliye compilation hamesha fail hoti hai aur message print hota hai. Yeh ek unsupported build configuration ko unconditionally reject karne ka common trick hai.
static_assert(-1, "check"); — pass hoga ya fail?
Pass hoga. Rule yeh hai ki "sirf tab fail hota hai jab value zero ho"; koi bhi non-zero value, negatives bhi, true count hoti hai. Sirf 0 diagnostic trigger karta hai.
C11 mein static_assert(0.0 == 0.0, "float check"); — legal hai?
Problematic. C11 ek constant integer expression maangta hai; ek floating comparison ek int (1) yield karta hai isliye yeh pass ho sakta hai, lekin floating-point constants par rely karna fragile aur non-portable hai — conditions ko integer-valued rakho.
Agar same scope par do static_asserts dono false hoon, toh kaun sa message dikhega?
Dono evaluate hote hain; ek conforming compiler har failing assertion ka message report karta hai (implementations early rok sakte hain, lekin build fail hoti hi hai). Koi kisi doosre ko silently override nahi karta.
Ek struct ke andar static_assert false condition ke saath — kya woh phir bhi fire karega?
Haan. C11 se, static_assert struct members mein appear kar sakta hai aur tab check hota hai jab type compile hoti hai — build fail hoti hai chahe us struct ka koi object abhi exist na karta ho.
static_assert(sizeof(char) == 1); — kya yeh kabhi false hoga?
Nahi — sizeof(char) C mein by definition 1 hai, har platform par. Isliye yeh particular assertion kabhi fail nahi ho sakta; yeh ek tautology hai, sirf intent ki documentation ke liye useful hai, real guard nahi.
Agar file mein condition mein enum value static_assert ke baad define ki gayi ho toh kya?
Yeh compile fail kar deta hai kyunki us point par woh naam abhi declared nahi hua. Constant expressions mein sirf wahi names reference karo jo already scope mein hain — order matter karta hai, bilkul kisi bhi doosri declaration ki tarah.