5.1.32 · D5 · HinglishC Programming

Question bankrestrict keyword — aliasing hint

2,651 words12 min read↑ Read in English

5.1.32 · D5 · Coding › C Programming › restrict keyword — aliasing hint

Shuru karne se pehle, ek line ka refresher un vocabulary terms ka jo har question mein kaam aata hai:

Har question ke peeche ki picture

Aliasing ek statement hai memory line par byte ranges ke baare mein. Pehla figure poore topic ko ek image mein dikhata hai — isko apne dimag mein rakhte hue jawab do.

Figure — restrict keyword — aliasing hint

Doosra figure dikhata hai kyun promise kaam karta hai: yeh ek strict per-element chain ko reorderable block mein badal deta hai.

Figure — restrict keyword — aliasing hint

Teesra figure parameter-reassignment nuance (6.7.3.1 p6) dikhata hai: promise value pe entry pe latch karta hai, isliye pehle parameter ko overwrite karna isko void kar sakta hai.

Figure — restrict keyword — aliasing hint

True or false — justify karo

Har ek statement hai. True/false decide karo aur reason do — reason hi poori baat hai. Jahan code alag ho, pichle figure ke do byte ranges picture karo.

restrict guarantee karta hai ki compiler faster code produce karta hai.
False — restrict sirf alias-analysis result ko relax karta hai jo compiler apne scheduler/vectorizer ko deta hai; yeh koi transform add nahi karta. Alias analysis normally do int* ke liye "may-alias" return karta hai (ek store a[i] par b[i] ke load ko may-alias kar sakta hai), jo reordering forbid karta hai; restrict isko "no-alias" tak downgrade karta hai (C99 §6.7.3.1 p4). Agar loop mein koi cross-iteration store→load hazard tha hi nahi, toh generated code byte-identical hoga. Speed ek consequence hai, kabhi promise nahi.
restrict aur const alag spellings ke saath ek hi kaam karte hain.
False — const (dekho const qualifier) ek modifiability qualifier hai: "is pointer ke through koi write nahi." restrict ek aliasing qualifier hai: "koi doosra, non-derived path is memory tak nahi pahunchta" (§6.7.3.1 p4). Yeh dono orthogonal hain; const int * restrict p dono cheezein ek saath assert karta hai.
Agar tum restrict likhte ho aur yeh jhooth hai, compiler error milega.
False — §6.7.3.1 poora burden programmer par dalta hai; compiler ko promise assume karne ki permission hai aur violation diagnose karna required nahi hai. Precise whole-program aliasing undecidable hai, isliye yeh silently tumpar trust karta hai — jhooth clean compile hota hai aur UB ban jata hai, jo aksar tabhi dikhai deta hai jab -O2/-O3 alias-analysis actually is fact ko use karta hai.
factor ko restrict mark karna compiler ko *factor ek baar load karne deta hai, neeche di gayi full declaration given.
True — declaration hai void scale(float * restrict v, float * restrict factor, int n){ for(int i=0;i<n;i++) v[i] *= *factor; }. restrict factor ke bina, alias analysis ko assume karna padta hai ki factor v[0..n) ke andar may point karta hai, isliye store v[i] = ... may-alias *factor ho sakta hai, forcing re-load of *factor har iteration. restrict factor prove karta hai ki factor ki range v ki range se disjoint hai, isliye *factor loop-invariant hai aur register mein hoist ho jata hai.
memcpy overlapping regions pe memmove ki tarah safe hai.
False — C standard memcpy(void * restrict s1, const void * restrict s2, size_t n) prototype karta hai; woh restricts overlap ko UB banate hain. memmove koi restrict use nahi karta aur uski spec explicitly overlap ki permission deti hai. Dekho memcpy vs memmove.
Do restrict pointers genuinely disjoint arrays mein promise honour karte hain even if unke addresses numerically close hain.
True — promise shared bytes ke baare mein hai, yaani kya ranges [p, p+len) aur [q, q+len) intersect karte hain (§6.7.3.1 p4 same object ki baat karta hai). Numerically adjacent lekin non-overlapping ranges koi byte share nahi karte, isliye koi aliasing nahi.
Same array ko do restrict parameters se pass karna legal hai jab tak tum kisi se bhi write nahi karte.
True lekin fragile — agar har access ek read hai, koi write→read hazard exist nahi karta, isliye §6.7.3.1 p4 (jo ek path se modification se trigger hota hai) kabhi violate nahi hota. Lekin ek parameter se ek bhi write plus doosre se koi bhi access = UB. Sabse safe hai kabhi alias mat karo.
restrict pointer ka type change karta hai.
True — yeh ek type qualifier hai (§6.7.3.1 p1), isliye int * restrict ek distinct qualified type hai; lekin yeh sirf aliasing contract change karta hai, pointer ka size ya representation nahi.
Non-pointer declaration par likha restrict syntax error hai.
False — §6.7.3.1 p1 restrict ko syntactically doosre types par allow karta hai lekin kehta hai iska koi effect nahi hota. Jaise int restrict x; intended nahi hai (compilers usually ussi jagah warn/reject karte hain), lekin jahan grammar ek non-pointer par qualifier allow karta hai, woh simply ignore ho jata hai. Yaad karne ka rule: restrict ka matlab sirf pointer-to-object par hota hai.

Error pakdo

Har snippet mein ek conceptual flaw hai (ya ek deliberate non-flaw). Usse naam do aur explain karo kyun yeh daata hai, pehle figure ke byte ranges trace karte hue.

void copy(int * restrict d, const int * restrict s, int n){ for(int i=0;i<n;i++) d[i]=s[i]; }
copy(a+1, a, 3);
``` ::: Error: `d = a+1` bytes `[a+1, a+4)` cover karta hai aur `s = a` `[a, a+3)` cover karta hai — yeh `a+1,a+2` par overlap karte hain. `restrict` promise jhooth hai → UB. Vectorization ke saath result unpredictable hai (`{a0,a0,a1,a2}` ya aur bura). `memmove` use karo.
 
```c
void f(int * restrict p){ int *q = malloc(4); *q = *p; free(q); }
``` ::: **Koi error nahi.** Machine model par, `malloc` aisa storage return karta hai jiska lifetime is call se *shuru* hota hai aur jiske paas koi aur live pointer nahi hai (standard kehta hai returned object *har doosre object se disjoint* hai, C99 §7.20.3). Isliye `q` ki range `p` ki range ke equal ya overlapping nahi ho sakti — `p` apne *object* tak akela path hi rehta hai. `restrict` doosri pointers ka *same* memory tak existence nahi rokta, sirf *different* memory ke pointers ka existence rokta hai.
 
```c
void g(int * restrict p, int * restrict q){ int *r = p; *r = 5; *q = *r; }
``` ::: Conditional error: `r` `p` se *based on* hai6.7.3.1 p4), isliye `*r = 5` `p` ke path se write hai. Agar runtime par `q` same object tak pahunchta hai, toh "`p` aur `q` disjoint hain" ka promise toot jaata hai → UB. `r` ko `p` se derive karna hamesha theek hai; `q` ko `p` ke object se alias karna violation hai.
 
```c
int x=0; int * restrict p=&x; int * restrict s=&x; *p=1; return *s;
``` ::: Error: `p` aur `s` do **non-derived** `restrict` pointers hain *same* object `x` ke; hum `p` se modify karte hain phir `s` se read karte hain. Yeh exactly wahi write-through-one, access-through-another pattern hai jo §6.7.3.1 p4 forbid karta hai → UB.
 
```c
void h(float * restrict v, int n){ float t=*v; for(int i=0;i<n;i++) v[i]+=v[0]; }
``` ::: **Koi error nahi.** `v[0]` aur `v[i]` dono `v` se *based on* pointers ke through access hote hain, isliye §6.7.3.1 p4 ki nazar mein yeh *same* path hain. Promise sirf *doosre, non-derived* pointers ko ban karta hai. Ek `restrict` pointer apne *aap* se overlap karna hamesha allowed hai.
 
```c
void k(int * restrict p, int n){ p = p + 1; *p = 0; }
``` ::: **Koi error nahi, lekin nuance important hai**6.7.3.1 p6): ek parameter ke liye, promise pointer ki value *on entry* par anchor hota hai. Yahaan `p` reassign karna phir bhi har access ko us entry value se *based on* chhodata hai, isliye promise kayam rehta hai. Contrast karo agले section ke edge case se jahan **unrelated** pointer ko reassign karna isko void kar deta hai.
 
---
 
## Kyun wale questions
 
Compiler ko `a[i]=b[i]+c[i]` mein kyun assume karna padta hai ki `a` `b` se overlap kar sakta hai? ::: Kyunki C ka aliasing model kisi bhi `int*` ko kisi bhi `int` object par point karne deta hai; compiler ka alias analysis isliye `a` vs `b`/`c` ke liye "may-alias" return karta hai aur `a[i]` ke store se kisi future `b`/`c` load ke change hone ke against defend karna padta hai. Dekho [[Compiler optimization & vectorization (SIMD)]].
 
Aliasing assumption specifically vectorization ko kyun block karta hai? ::: SIMD kaafi elements *ek saath aur out of order* process karta hai (doosra figure). Yeh tab hi legal hai jab batch mein ek store batch mein ek load ko invalidate na kar sake. May-alias strict per-element load→add→store chain force karta hai, block form ko khatam kar deta hai.
 
`restrict` "programmer ka kaam" kyun hai compiler ka nahi? ::: Poore program mein do arbitrary pointers kabhi alias nahi karte isko prove karna undecidable hai, isliye §6.7.3.1 guarantee ko us insaan par shift kar deta hai jo call sites jaanta hai, aur alias analysis ko isko *assume* karne deta hai.
 
Promise todna kabhi kabhi `-O0` par "kaam karta hai" lekin `-O2` par kyun fail hota hai? ::: `-O0` alias facts ko bahut kam use karta hai, isliye naturally memory re-read karta hai aur accidentally correct ho sakta hai; `-O2` no-alias fact par *act karta hai* (hoisting, reordering, vectorizing), jhooth ko wrong output ke roop mein expose karta hai.
 
Local mein ek `restrict` pointer copy karna promise se "escape" karne ka tarika kyun nahi hai? ::: Copy original se *based on* hai6.7.3.1 p4), isliye uske through access abhi bhi original path se access count hote hain. Promise *data lineage* follow karta hai, variable name ko nahi.
 
`restrict` thread safety ya `volatile` ke baare mein kyun kuch nahi kehta? ::: Yeh sirf single-threaded, per-object *aliasing* contract hai. Concurrency aur hardware-visible side effects memory models aur `volatile` se govern hote hain, jo alag mechanisms hain.
 
Multi-level pointer `restrict` ko confusing kyun bana sakta hai? ::: `int * restrict * p` mein, `restrict` *inner* pointer type qualify karta hai (woh `int*` jo `*p` yield karta hai), `p` ko nahi; promise un objects ke baare mein hai jahan woh inner pointers pahunchte hain, isliye disjointness ke baare mein reason karne se pehle tumhe track karna hoga ki *kaunsa* level qualifier carry karta hai.
 
---
 
## Edge cases
 
Jab `n == 0` ho aur loop kabhi nahi chale toh `restrict` ka kya matlab hai? ::: Kuch bhi access nahi hota, isliye §6.7.3.1 p4 kabhi trigger nahi hota; promise trivially satisfied hai even if ranges overlap karte hain. Pointers equal bhi ho sakte hain.
 
Kya `T * restrict p = NULL;` legal hai? ::: Declare karne ke liye haan — ek null `restrict` pointer theek hai jab tak tum isko kabhi *dereference* nahi karte. Promise actual accesses ko constrain karta hai, aur ek null pointer kuch bhi access nahi karta.
 
Agar do `restrict` pointers equal hain lekin tum sirf dono se *read* karte ho, kya UB hai? ::: Nahi — §6.7.3.1 p4 tab hi violate hota hai jab ek path se *modification* ek alag, non-derived path se kisi access ke saath coexist kare. Sab-reads kabhi modify nahi karta, isliye yeh safe hai.
 
Kya function parameter par `restrict` function return ke *baad* memory ko constrain karta hai? ::: Nahi — §6.7.3.1 p6 promise ko function body (pointer ke block) se tie karta hai. Call khatam hone ke baad, doosre pointers freely us memory tak pahunch sakte hain.
 
Agar tum ek `restrict` **parameter** ko pehle access se pehle kisi unrelated pointer pe reassign karo, kya promise abhi bhi naye target ko bind karta hai? ::: Dhyan se — promise value *on entry* par anchor hota hai6.7.3.1 p6, teesra figure). Accesses ek aisa pointer ke through jo entry value par *based on* nahi hai, woh promise ke bahar hain, isliye tum intended guarantee *void* kar sakte ho; ulta entry value (aur usse based on cheezein) ke through accesses bound rehte hain. Rule of thumb: agar guarantee chahte ho toh restrict parameters reassign mat karo.
 
Agar ek `restrict` pointer ki region doosre ki ek byte adjacent ho, exactly `q = p + n`? ::: Legal — `p` `[p, p+n)` cover karta hai, `q` `p+n` par start hota hai; ranges touch karte hain lekin koi byte share nahi karte. Disjoint ka matlab hai koi shared byte nahi, aur yahan hai bhi nahi.
 
Kya ek single `restrict` pointer *apne aap* se overlap kar sakta hai, jaise `v[0]` read karte hue `v[i]` write karo? ::: Haan — dono accesses same `restrict` pointer se *based on* hain, isliye yeh same path hain aur §6.7.3.1 p4 apply nahi hota. Self-overlap hamesha theek hai.
 
Do `restrict` pointers same **struct ke alag members** ke — kya yeh aliasing hai? ::: Nahi — distinct members struct ke distinct, non-overlapping bytes occupy karte hain, isliye `&s.a` aur `&s.b` ke pointers alag objects tak pahunchte hain aur promise honour karte hain, even though woh ek struct mein rehte hain. (Lekin *poore* struct ka pointer dono se overlap karega.)
 
Kya non-pointer type par `restrict` kuch karta hai? ::: Nahi — §6.7.3.1 p1 kehta hai non-pointer types par yeh *allowed hai lekin koi effect nahi* hota. Sirf ek pointer-to-object aliasing meaning carry karta hai; kahin aur yeh silently no-op hai.
 
---
 
> [!recall]- Traps ka ek-line summary
> Almost har trap teen jhooton mein se ek hai: (1) `restrict` aur `const` ko confuse karna (modifiability vs aliasing), (2) yeh sochna ki compiler isko *check* karta hai6.7.3.1 yeh tumpar dalta hai), ya (3) yeh bhool jaana ki promise **based-on** pointers ko *same* path maanta hai, jabki sirf ek *alag, non-derived* path plus ek write UB cause karta hai.
 
## Connections
- [[Pointers in C]]
- [[const qualifier]]
- [[Pointer aliasing]]
- [[memcpy vs memmove]]
- [[Compiler optimization & vectorization (SIMD)]]
- [[Undefined behaviour in C]]
- [[C99 standard features]]