Types of Pointers in C as it is…!

पोस्ट ला नाव असं का दिल असेल?

आपण लहानपणा पासून बघत आहोत, ऐकत आहोत “भगद्वतगीता – जशी आहे तशी”… ना आपण ती वाचतो, समजा अगदीच ती वाचली तर ना आपणाला ती समजते, आणी समजा ती समजली तर आपल्याला समजण्याची पद्धत हि दुसऱ्यापेक्षा वेगळी असू शकते कारण श्रीकृष्णाचे रुपं च तसं होत अर्जुना ला दिसलेलं…! असो…

मी या पोस्ट मध्ये Types of pointers in C वर लिहायचं ठरवलयं…

ज्या व्हेअरेबल मध्ये दुसऱ्या व्हेअरेबल चा address ठेवता येतो अशा प्रकारच्या व्हेअरेबल ला पॉइंटर व्हेअरेबल म्हणतात इतकी सोपी व सरळ व्याख्या असुन सुद्धा पॉइंटर वापरतांना झालेला गोंधळ हा प्रोग्रॅमरच्या पाचवीला पुजलेला असतो.

Bhagavad-Gita

शिवाय भगवद्गगीते मध्ये जशी कृष्णाची अनंत रुपे अर्जुनासमोर उभी रहातात त्याच प्रमाणे पॉइंटरची वेगवेगळी रुपं सुद्धा C प्रोग्रॅमरला दिसत जातात.

मनात आलं म्हणून हि पोस्ट लिहीते आहे… हि सगळी रुपं मला ज्या प्रमाणे दिसली तशी…!

आकर्षक images टाकून TV किंवा Newspaper प्रमाणे TRP वाढवण्याचा माझा मुळीच उद्देश नाही पण मी ज्यावेळी पॉइंटर ला बघते त्यावेळी मला तो श्रीकृष्णासारखाच दिसतो म्हणून हि image टाकली…! 🙂

Integer/float/character pointer

C language मधील बेसीक डेटा-टाइप असला व त्याच्या व्हेअरेबल्सचा address ठेवायचा असला तर तुम्हाला corresponding प्रकारचा पॉइंटर म्हणजेच पॉइंटर व्हेअरेबल लागते. जसे की या तीन व्हेअरेबल्स चे पॉइंटर्स कसे आहेत पहा या प्रोग्रॅम मध्ये दिसेल…

खरं तर पॉइंटर हा derived data type. म्हणजेच basic data type  पासून तयार झालेला किंवा केलेला म्हणा हवं तर. म्हणून की काय डेनीस ने star (*) operator हा पॉइंटर डिक्लेअर करण्यासाठी सुचवला. डिक्लेअर करण्यासाठी तोच व पॉइंटर ज्या ठिकाणी पॉइंट करतो त्या ठिकाणची व्हॅल्यु मिळवण्यासाठी सुद्धा तोच. म्हणजे star operator याच ठिकाणी double role करतोय. शिवाय binary operator या रुपात काम करतांना तो multiplication operator म्हणून सुद्धा काम करतो…

आता integer pointer, character pointer, float pointer हि पॉइंटर्सची साधी-भोळी रुपं… पण हि खरं तर वादळापुर्वीची शांतता असते कारण खरे रंग तो नंतर दाखवायला सुरवात करतो ज्यावेळी तुम्ही प्रथम array शिकतांना भेटता त्यावेळी.

Array च्या पहील्या element च्या address ला base address म्हणतात व तो array च्या नावामध्ये स्टोअर केला जातो किंवा असतो असे काहीतरी तुमच्या कानावर पडते. तुमच्या पॉइंटर विषयीच्या ज्ञानाला पहीला सुरुंग बसतो तो या ठिकाणी… तो धक्का सुद्धा तुम्ही कष्टाने पचवता. पण तेवढ्यात पॉंइटर arithmetic हा प्रकार तुमच्या नजरेला येतो. त्या ठिकाणी अनेक विद्यार्थ्यांची जी घसरण सुरू होते ती शेवटपणे थांबत नाही कारण त्या नंतर तुमच्या कानावर double dimensional array, string manipulation, structure pointer येउन पडतात व तुम्ही अर्धमेले व्हायला सुरवात होते. शेवटी file pointer हा जो काही येतो तो तुम्हाला पुर्ण नेस्तानाबूत करूनच शांत होतो. 🙁

त्या नंतर मग तुम्ही जे काही शिकता म्हणजे उदा. Dynamic memory allocation मध्ये भेटणार void pointer, data structure मध्ये लागणारे next, previous, first नावाचे pointer, dangling pointer हे जणू तुम्ही तटस्थ वृत्तीने ऐकायला (शिकायला अथवा समजायला नव्हे) सुरवात करता. अर्थात तुमच्या कडे दुसरा मार्गही नसतो हे लक्षात घ्या…! या व्यतिरीक्त function pointer, far pointer, huge pointer, near pointer, wild pointer अशा प्रकारचे जे काही आहेत ते आपण नंतर कधीतरी शिकुया व आत्ता Java सारखी pointer-free language शिकुन मोकळे होउया असा विचार करता…! असो मी या सर्व पॉइंटरची ओळख तुम्हाला करून देणार आहे. ओळख करून घ्यायची कि नाही हे तुम्ही ठरवा… मी तुम्हाला भेटीला घेउन येते ठरावीक अंतराने…

तर मग कशी आहेत रुपं आहेत या सर्व पॉइंटरची…?

आपण सुरवात constant pointer पासून करू…

Constant pointer

विद्यार्थी array शिकतात, स्ट्रिंग टॉपीक शिकतात. प्रोग्रॅम्स सुद्धा लिहीतात. व स्ट्रक्चर, फाईल हॅंडलींग शिकुन मोकळे होतात. पण

#include<stdio.h>
int main()
{

int num[ 5 ] = { 3, 4, 5, 6, 7 };
int i;

for(i=1;i<=5;i++)
{

printf(“%d…”,*num);
num++;

            }

return 0;

}

आणी

#include<stdio.h>
int main()
{

char name[50];
name = “C Programming”;

puts(name);

return 0;

}

या दोनही प्रोग्रॅमचे आउटपुट विचारले की सांगायला मात्र चुकतात. हे दोनही प्रोग्रॅम कंपाइल टाइम एरर देतात त्याचे कारण म्हणजे कॉंन्स्टंट पॉइंटर असते. तुम्ही ज्यावेळी array व स्ट्रिंग डिक्लेअर करता त्यावेळी पहील्या प्रोग्रॅम मध्ये num या array च्या नावामध्येच व स्ट्रिंग च्या name मध्ये array चा base address ठेवण्याचे काम automatically केले जाते. हा पॉंईटर internally तयार करण्याचा उद्योग कंपायलर करत असतो. व हा कॉंन्स्टंट पॉइंटर कॅटेगरीत मोडतो. त्या कारणामुळेच तुम्ही स्ट्रिंग initialize करू शकता, स्कॅन करू शकता पण assignment करू शकत नाही. कारण हा पॉइंटर साधा पॉइंटर नसतो तर कॉंन्स्टंट पॉइंटर असतो. त्यामुळे तो दुसरीकडे पॉइंट करू शकत नाही… हा खाली दिलेला प्रोग्रॅम काळजीपुर्वक पहा. तसेच num++ करू शकत नाही कारण num हा सुद्धा constant pointer या category मध्ये येतो.

अशा प्रकारचा pointer तुम्ही सुद्धा डिक्लेअर करू शकता. जसे की…

int x = 5;
int y = 10
const int *ptr = &x;

*ptr = 20;                                 // invalid
printf(“%d”,x);

मात्र या ठिकाणी const ची position मात्र महत्वाची आहे. कारण जर तुम्ही हाच प्रोग्रॅम

int x = 5;
int y = 10;
int *const ptr = &x;

*ptr = 20;                                 // valid

ptr = &y;                                  // invalid
printf(“%d”,x);

असा लिहीला तर त्याचा अर्थ बदलतो. वर दिलेली दोन examples मध्ये array च्या नावामध्ये base address स्टोअर करतांना जो पॉइंटर internally तयार केला जातो त्याची जातकुळ या पॉइंटर सारखी असते

हे सर्व चांगल्या पद्धतीने समजण्यासाठी मी लिहीलेला Interpreting complex C declarations हि पोस्ट तुम्ही वाचली तर मी काय म्हणते आहे ते तुम्हाला कळेल.

या पोस्टमध्ये मी इतकेच लिहीते. पुढील पोस्ट मध्ये Null Pointer वर सविस्तर चर्चा करते.

function pointer in C

C programming language मध्ये असे काही topics आहेत कि ते अभ्यासक्रमात घेतले जात नाहीत अथवा इतक्या brief मध्ये संपवले जातात कि त्या topics विषयी अज्ञान किंवा भिती अथवा दोनही कायमच्या रहातात. function pointer हा अशाच प्रकारचा एक टॉपीक.  Typecast, bit fields, union, bit operators पेक्षा सुद्धा जास्त सापत्नपणाची (Step-motherly treatment) वागणूक मिळालेल्या या टॉपीकविषयी मी लिहीणार आहे. कारण C++ मध्ये virtual function या महत्वाच्या chapter चे fundamental concepts या topic मध्ये दडून बसलेले आहेत.

हव तर pointer म्हणजे काय हे एकदम सोप्प्या भाषेत समजावून घ्यायच असेल तर हा व्हिडीओ पहाच

प्रथम integer pointer, character pointer, float pointer या सारखे साधे pointer वापरत गेले कि एव्हाना गुंतागुंत झालेली असते.  त्या नंतर भरीस भर म्हणून structure pointer, string pointer हे वेगवेगळे शब्द कानावर पडतात. शेवटी file pointer म्हणजे आता बस्स…! अशी अवस्था होते व या सगळ्या धामधुमीत function pointer दुर्लक्षीला जातो तो कायमचाच.

function pointer

function pointer

आता आपल्याला हे माहीत आहे कि प्रोग्रॅम लिहून, कंपाइल व रन करतांना मेन मेमरीमध्येच म्हणजेच Data Segment variables व Code Segment मध्ये compiled व executable code ठेवला जातो. म्हणजेच variables साठी जशी मेमरी दिली जाते त्या प्रमाणे functions साठी सुद्धा memory block दिले जातात. आणी मेमरी आली म्हणजे त्याचा address हा आलाच.

आता या फंक्शनचा address स्टोअर करायला अर्थातच pointer लागणार व त्यालाच function pointer म्हणतात. आणी हे function pointer declare करण्याचे प्रकरणच जरा confusing असल्यासारखे आहे. पण तेच तर मी सोप्या पद्धतीने सांगणार आहे. समजा आपण एक छोटासा प्रोग्रॅम लिहीला. जसे की

#include<stdio.h>
void printmessage( );
int main( )
{

printmessage( );
printf(“Address of function = %un”,printmessage);
return 0;

}

void printmessage( )
{

printf(“In function printmessagen”);

}

या ठिकाणी main function मधील printf function मध्ये printmessage असे argument आहे. आपणच लिहीलेल्या user defined function चे फक्त नाव लिहीले आहे. हा प्रोग्रॅम कंपाइल व रन केला तर तुम्हाला जे output मिळते ते म्हणजे printmessage या फंक्शनचा तो memory मधील address असतो. Array चे नाव म्हणजे array च्या पहील्या element चा address असतो त्या प्रमाणेच printmessage या function च्या नावामध्ये function चा address असतो. त्याच प्रमाणे तुम्ही main function चा address सुद्धा print करू शकता.

आता आपण अजून एक साधा प्रोग्रॅम लिहू व त्या नंतर पाहूया हे function pointer काय प्रकरणं आहे ते…

#include<stdio.h>
void display();
int main()
{

int x;
static int y;
int *ptr;
void (*ptr_to_display)();

ptr_to_display = display;

(*ptr_to_display)( );

ptr = (int*) malloc(sizeof(int));
printf(“Address of x = %un”,&x);
printf(“Address of y = %un”,&y);
printf(“memory given by ptr = %un”,ptr);
printf(“Address of display function = %un”,display);
printf(“Address of main function = %un”,main);
printf(“Address of printf function = %un”,printf);
printf(“Address of scanf function = %un”,scanf);
free(ptr);

}
void display()
{

printf(“In display functionn”);

}

हा प्रोग्रॅम तुम्ही compile व रन केला तर तुम्हाला

  • x या auto variable चा stack वरील
  • y या static variable चा static memory वरील
  • ptr ला dynamic memory allocation ने केलेल्या heap वरील memory चा addresses मिळतील
  • तसेच तुम्हाला printf, scanf, main या library functions चे आणी display या user defined functions चे memory addresses मिळतील.

या ठिकाणी void (*ptr_to_display) ( ); असे एक declaration केले आहे ते function pointer चे declaration आहे व हेच confusing आहे. म्हणून आपण त्याचे dissection करूया.

  1. आपल्याला display या फंक्शनचा address store करायचा आहे व त्याचा return type void आहे म्हणून आपण एक फंक्शन पॉइंटर declaration void असे सुरू केले आहे.
  2. इतर pointer variable ला नाव असते त्याप्रमाणे या variable चे नाव ptr_to_display असे आहे
  3. ते pointer variable असल्यामुळे त्याच्या मागे * जोडला आहे.
  4. आता या *ptr_to_display च्या दोनही बाजूला round brackets आहेत व त्यामुळेच compiler ला हा function pointer आहे असे कळते. व हाच सर्वात कळीचा मुद्दा आहे कारण जर round brackets टाकले नाहीत तर मात्र declaration void *ptr_to_display असे होइल व त्याचा अर्थ ptr_to_display हा void pointer आहे असा होतो.
  5. त्या नंतर pair of round brackets आहेत ते म्हणजे  ज्या function चा pointer करायचा त्या function च्या arguments साठी असते. या ठिकाणी display function arguments घेत नसल्यामुळे brackets empty आहेत.

आता हे वरील स्टेटमेंट एकाच वाक्यात सांगायचे असेल तर “ptr_to_display हा no arguments घेणाऱ्या व void return करणाऱ्या  function चा pointer आहे” असे सांगता येइल.

त्यामुळेच ptr_to_display = display; या assignment स्टेटमेंट मुळे display function चा address ptr_to_display या function pointer मध्ये store होइल.

pointer indirection operator वापरुन जसे pointer ज्या ठिकाणी point करत आहे त्या ठिकाणचे contents access करता येतात त्याच प्रमाणे आपण function pointer वापरुन function ची मेमरी access करणे किंवा function call करण्याची प्रक्रिया सुद्धा करता येते. जसे की…

त्या पुढील स्टेटमेंट म्हणजेच (*ptr_to_display) ( ); actually display function call करण्याचे काम करेल. अर्थात तुम्ही ptr_to_display( ); असे लिहीले तरी सुद्धा display function invoke होतेच.

इतके उद्योग करून याचा उपयोग काय असा प्रश्न साहजीकच पडतो. पण मेमरी बरोबर खेळणे हीच तर C language ची खासीयत आहे. त्यामुळे resident memory programs लिहीण्यासाठी, virus लिहीण्यासाठी, आणी anti-virus लिहीण्यासाठी function pointer चा सर्रास वापर केला जातो.  

Heart of C

See on Scoop.itC Programming Language

First question asked about C Marathi to us by everybody in all educational institutes and by all professionals is How we have covered Pointers…! Our answer is “ये तो हमारे बायें हाथ का…

C Marathi‘s insight:

Innovative e-learning contents of Programming language developed by C Marathi team

See on www.cmarathionline.com