Theory
દરેક પ્રકારના ઘર માટે એક ચબરખી
પાછલા lesson માં તમે તમારો પહેલો pointer લખ્યો. આજે drill: marks program માં એક int marks, એક float percentage અને એક char grade છે, અને દરેકને પોતાનો pointer જોઈએ.
પહેલી સહજ સમજ: "address એ address છે, એક જ pointer type બધા માટે ચાલવો જોઈએ."
C અસહમત છે, સારા કારણસર: જ્યારે courier address પર પહોંચે, એને ખબર હોવી જોઈએ કે 4 bytes ઉપાડવાના છે કે 1, અને એમને કેવી રીતે વાંચવા. ચબરખી એક TYPE સાથે રાખે છે.
Theory
દરેક type નો એક pointer
int marks = 78; int *pi = &marks;
float perc = 78.5; float *pf = &perc;
char grade = 'A'; char *pc = &grade;
નિયમ: pointer નો type એની સાથે મેળ ખાય છે જેને એ point કરે છે. કેમ? Dereference ને box નું size અને encoding ખબર હોવું જોઈએ: *pi 4 bytes ને int તરીકે વાંચે છે, *pc 1 byte ને char તરીકે. એક float ને કોઈ int પર point કરો અને compiler વાંધો ઉઠાવે છે, અને જો ફરજ પાડી, તો pf એ int ના bytes ને float બકવાસ તરીકે વાંચશે, Unit 1 નો costume-mismatch વાળો garbage, હવે memory ના સ્તરે.
Theory
ચબરખી પર parcel નું size
કોઈ godown માંથી pickup ની એક address slip ફક્ત એ નથી કહેતી કે ક્યાં, એ પણ કહે છે કે શું લેવાનું છે: "4-byte int નું crate" કે "1-byte char નું envelope". સાચા address પર ખોટી slip વાળો courier ખોટી માત્રા ઉપાડી લે છે અને માલ બગાડી નાખે છે. અને એક ખાલી slip? એ છે NULL: એક પ્રામાણિક "હજી કોઈ મંઝિલ નથી", કોઈ આડેધડ લખેલા address વાળી slip (એક uninitialized, wild pointer) કરતાં અગણિત ગણી સલામત.
Practical
આખો pointer drill
#include <stdio.h>
int main() {
int marks = 78;
float perc = 78.5;
char grade = 'A';
int *pi = &marks;
float *pf = &perc;
char *pc = &grade;
int *safe = NULL; /* points nowhere, on purpose */
printf("%d %.1f %c\n", *pi, *pf, *pc);
if (safe != NULL) printf("never runs\n");
return 0;
}This example runs in Gri-Learn on the web, where you can edit it and see the output.
Quiz
કોઈ float ના pointer ને int* ને બદલે float* કેમ declare કરવો જરૂરી છે?
- Dereferencing type થી જાણે છે કે કેટલા bytes વાંચવા અને એમને કેવી રીતે interpret કરવા
- એ ફક્ત એક naming convention છે; કોઈ પણ pointer type એકસરખું કામ કરે છે
- float* pointers memory ના એક ખાસ ભાગમાં store થાય છે
- int* pointers મોટા addresses રાખી શકતા નથી
Show the answer
Dereferencing type થી જાણે છે કે કેટલા bytes વાંચવા અને એમને કેવી રીતે interpret કરવા
બધા pointers એકસરખા દેખાતા addresses રાખે છે; TYPE એ dereference માટે સૂચના છે: pf 4 bytes ને IEEE float તરીકે વાંચે છે, pc 1 byte ને એક character તરીકે. ખોટો type = ખોટી width + ખોટું interpretation = garbage. "pointer types કેમ જરૂરી છે?" એ કાયમી exam short-answer છે, અને એ જ એનો પૂરા-marks વાળો જવાબ છે.
Theory
NULL અને typeless void*
NULL: જાણીજોઈને ક્યાંય-નહીં. int *p = NULL; કહે છે "હજી કોઈ target નથી", અને code એને CHECK કરી શકે છે: if (p != NULL). એનાથી ઉલટું wild pointer: declare કર્યો, ક્યારેય initialize નહીં, એક આડેધડ address રાખે છે, એને dereference કરો અને program corrupt થાય કે crash. NULL checkable છે; wild અંધાધૂંધી છે.
*void \vp: generic ચબરખી, કોઈ પણ type નો address લે છે (`vp = &marks; vp = &perc;`). કિંમત: એને સીધું dereference કરી શકાતું નથી*, C ને parcel નું size ખબર નથી. પહેલાં cast કરો: `(int )vp`. Libraries એક જ function થી દરેક type ને સેવા આપવા માટે void વાપરે છે.
Think first
ખતરો ઓળખો
ત્રણ pointers: int a = &marks; int b = NULL; int *c; (ક્યારેય assign ન થયો). એમને rank કરો: કયું dereference સલામત છે, કયું એક પાક્કો crash છે જેને તમે ઓછામાં ઓછું TEST કરી શકો, અને કયું સૌથી ખરાબ છે?
Show the answer
*a સલામત છે: એ એક સાચા box ને target કરે છે. *b crash કરે છે, પણ ધારી શકાય એમ, અને code એની ચોકી કરી શકે છે: if (b != NULL). *c સૌથી ખરાબ છે: એક wild pointer જે આડેધડ garbage રાખે છે; એને dereference કરવાથી data છાનેમાને corrupt થઈ શકે અને demo વાળા દિવસ સુધી "કામ" કરતો રહે. દરેક C programmer ની દીવાલ પર છપાયેલો બોધ: pointers ને initialize કરો, કોઈ target પર કે NULL પર, એમને ક્યારેય wild ન છોડો.
Quiz
void *vp = &marks; vp દ્વારા int વાંચતાં પહેલાં શું જરૂરી છે?
- એક cast: *(int *)vp, કારણ કે void* કોઈ size માહિતી રાખતું નથી
- કંઈ નહીં: *vp સીધું કામ કરે છે
- vp ને પહેલાં NULL set કરવો પડે
- void pointers ક્યારેય વાપરવા લાયક બનાવી શકાતા નથી
Show the answer
એક cast: *(int *)vp, કારણ કે void* કોઈ size માહિતી રાખતું નથી
void WHERE store કરે છે પણ WHAT નહીં: કોઈ type નહીં, કોઈ byte-width નહીં, એટલે સાદું vp ગેરકાયદે છે. Cast (int )vp એ address ને થોડી વાર માટે એના સાચા type માં પહેરાવી દે છે, અને પછી dereference જાણે છે કે 4 bytes ને એક int તરીકે વાંચવા. "Generic પણ cast-before-use" એ void ની આખી exam વાર્તા છે.
Watch out
Marks ક્યાં કપાય છે
Type mismatches: float pf = &marks કેટલાક setups પર warnings સાથે compile થાય છે અને ખરાબ વર્તન કરે છે; types હંમેશા મેળવો. Wild pointers: int p; p = 5; એ corruption ની એક lottery છે, કોઈ target પર કે NULL પર initialize કરો. cast વગર void\ ને dereference કરવું*: compile error, અને WHY જાણવું (કોઈ size માહિતી નહીં) એ marks અપાવે છે. Style note: int p અને int p બંને compile થાય છે; એ NAME સાથે જોડાય છે (int* a, b એક pointer અને એક int declare કરે છે, એક ચાલાક classic).
Theory
આગળ: pointers ચાલતાં શીખે છે
આગળના lesson ની એક ઝલક: pi એક address રાખે છે, તો pi + 1 શું છે? Address-વત્તા-એક-byte નહીં, C વધુ સમજદાર છે: એ એક આખા box આગળ વધે છે (int માટે 4 bytes, char માટે 1), અને એ જ pointers અને arrays ને પાક્કા દોસ્ત બનાવે છે. Pointer arithmetic, આગળ.
Summary
Key takeaways
- દરેક type પ્રમાણે declare કરો: int pi, float pf, char *pc; type એ target સાથે મેળ ખાવો જોઈએ.
- Type, dereference ને કહે છે કે કેટલા bytes વાંચવા અને એમને કેવી રીતે interpret કરવા.
- NULL = જાણીજોઈને ક્યાંય-નહીં, if (p != NULL) થી checkable; wild pointers = આડેધડ અંધાધૂંધી.
- દરેક pointer initialize કરો: કોઈ સાચા target પર કે NULL પર, એને ક્યારેય wild ન છોડો.
- void કોઈ પણ address રાખે છે પણ dereference પહેલાં cast કરવો જરૂરી છે: (int *)vp.
- યાદ રાખવાની યુક્તિ: ચબરખી parcel નું size જણાવે છે; ખાલી ચબરખી, આડેધડ લખેલી ચબરખી કરતાં સારી.