Interpreting complex declarations in C

 

march

Left… Right… Left… Right… Left…. Left…. Left… Right… Left

लहानपणी NCC ला कवायत करत असतांना हे कानावर पडायचे… तुम्ही केली असेल तर तुम्हाला सुद्धा आठवत असेल कदाचित… हाच नियम जर तुम्ही थोडासा बदल करून पाळला तर C programming languages मधील complex declarations तुम्हाला वाचायला अडचण येणार नाही… कसे तेच मी सांगणार आहे या पोस्ट मध्ये…

मी १९९८ साली C language शिकल्यानंतर जॉब शोधत होते. त्यावेळचा एक प्रसंग आठवतो. त्यावेळी माझी एक मैत्रीण सॉफ्टवेअर कंपनीमध्ये काम करत होती. एकदा ती म्हणाली schaum series च्या पुस्तकातील C type declaration फक्त वाचायला आली ना तुला तर जॉब मिळुन जाइल. असे अनेक सल्ले मिळायचे तसाच तो सुद्धा होता. पण सल्ला देणारी व्यक्ती ते कसे करायचे हे कधीच सांगत नाही… तुमचा हाच अनुभव असेल ना…?

असो… तर समजा interview ला तुम्हाला

float * (* (*ptr)(int))(double **,char c);

हे डिक्लेरेशन जर वाचायला सांगीतले आणी जर तुम्ही C language शिकतांना जरी अनेक प्रोग्रॅम्स लिहीले असतील व प्रोजेक्ट सुद्धा केला असेल तरी या ठिकाणी तुमची दांडी उडणार हे नक्की. हा काय वेडपटपणा आहे असे तुम्ही interview घेणाऱ्याबद्द्ल चरफडतपणे मनात म्हणाल. हे सर्व काही होउ नये असे वाटत असेल तर पहा तुम्हाला हि पोस्ट मदतीला येते का ते…

अशा प्रकारची डिक्लेरेशन्स अथवा फंक्शन प्रोटोटाइप जरी प्रोग्रॅम मध्ये क्वचितच वापरली जात असली तरी तुमचे C चे ज्ञान दोन-चार प्रश्नात चेक करण्यासाठी हे प्रश्न विचारले जातात. कारण तुम्हाला असा प्रश्न सोडवायला C मधील Data Types, function, array, pointers, string इत्यादीचे सर्व ज्ञान असण्याची जरूरी असते. मग हे सर्व असल्यानंतर कसे सोडवायचे हे…? मात्र हे लक्षात ठेवा की अशा प्रकारची डिक्लेरेशन्स तुम्ही प्रोग्रॅम लिहीतांना लिहू नका…!

spiral rule

तर यासाठी खाली दिलेली पद्धत वापरायची… या पद्धतीला स्पायरल अथवा क्लॉकवाइज रुल असेसुद्धा म्हणतात

  1. प्रथम सगळ्यात आत असलेले व्हेअरेबलचे नाव येइल
  2. शेवटी डिक्लेरेशनच्या सुरवातीला असलेला शब्द येइल
  3. वाचताना शक्य तितके उजवीकडे (Right) जायचे. थांबण्याची जरूरी वाटली कि थांबायचे मग शक्य तितके डावीकडे (left) जायचे. नंतर पुन्हा उजवीकडे जायचे… हे करत असतांना तुम्हाला जे काही मिळेल ते पहील्या व शेवटच्या शब्दामध्ये भरत जायचे…

नाही कळाले ना…? सांगते मी तुम्हाला

आपण काही साधी उदाहरणे घेउ.

04

int x; हे आपण कसे वाचतो तर x (या नंतर उजव्या बाजूला जायचे पण तिकडे काहीच नाही आहे…! म्हणून डाव्या बाजूला जायचे) is a variable whose data type is int

int *ptr; हे कसे वाचतो तर ptr (या नंतर उजव्या बाजूला जायचे पण तिकडे काहीच नाही आहे…! म्हणून डाव्या बाजूला जायचे) is a pointer variable (या ठिकाणी पुन्हा उजव्या बाजूला पहायचे) which can contain an address of integer

समजा आपण

05

अजून एक महत्वाचा कंसेप्ट म्हणजे अनेक वेळा विद्यार्थ्यांचा int *ptr; आणी int* ptr; या दोन स्टेटमेंट पैकी सर्वात योग्य कोणते कारण दोनही पद्धती प्रोग्रॅम मध्ये चालतात. तरी सुद्धा K&R style प्रमाणे पहीली पद्धत जास्त योग्य. कारण त्यामुळे स्टेटमेंट योग्य पद्धतीने वाचता येतेच शिवाय गोंधळ सुद्धा होत नाही जसे की समजा

int* x, y;

या मध्ये x and y दोन्ही pointer variables आहेत की फक्त x हे pointer variable आहे…? गोंधळात पडला असाल कदाचीत…! असो तुम्हीच चेक करा… मला पुन्हा विषयाकडे वळायला परवानगी द्या… तर समजा

double area(int,int); असे डिक्लेरेशन घेतले तर…. area (या नंतर उजव्या बाजूला जायचे व या ठिकाणी फंक्शन चा opening ब्रॅकेट आहे) is a function which takes 2 arguments viz. integer and integer (या ठिकाणी closing bracket मुळे थांबायला हवे व डाव्या बाजूला जायला हवे) and returns double

अजून एक  example पाहू…. थोडे अजून अवघड…

char *name[10];

हे कसे वाचायचे…? तर name is an array of 10 pointers having type char

आता अजून थोडे अवघड व क्लिष्टीक example पाहू जसे की

06

char *(*fp) (int,float*);

मग हे कसे वाचायचे तर… fp is a (या ठिकाणी उजव्या बाजूला गेल्या नंतर ब्रॅकेट येतो म्हणून थांबायचे व डाव्या बाजूला जायचे) pointer (या ठिकाणी पुन्हा ब्रॅकेट आल्यामुळे थांबून उजव्या बाजूला जायचे) to function taking (or passing) two arguments viz. integer and float pointer (या ठिकाणी फंक्शन्चा क्लोजींग ब्रॅकेट आला आहे म्हणून थांबायचे व पुन्हा डाव्या बाजूला जायचे) and returning pointer (पुन्हा उजव्या बाजूला जायचे परंतू येथे सेमी कोलन आहे म्हणून डाव्या बाजूला जायचे) to character

येथे अशीच काही examples मी येथे देत आहे. प्रत्येक डिक्लेरेशन समजावून घ्या…

int (*p) [5];

p is pointer to an array having size 5 of integers

char *x[ 3 ] [ 4 ];

या ठिकाणी वर पाहील्याप्रमाणे final expression x……………………..char अशा प्रकारचे असेल ज्या मध्ये आपल्याला बाकी सर्व details भरायला लागतील… जसे की

  1. x       :  then Turn right
  2. is an array of 3 : then turn right as array notation[ ] has got precedence over pointer *
  3. Arrays of 4 : then take left
  4. pointers       : then take right and you will reach semi colon
  5. to char

x is an array of 3 arrays of 4 character pointers

int *(*a [ 10 ] ) ( );

  1. a is :     then take right
  2. an array of size 10: then take left
  3. pointers :     then take right
  4. to function :           then take left
  5. and returning pointer :           take right
  6. to integer :     take left

मग या पोस्टच्या सुरवातीला जे डिक्लेरेशन दिले आहे ते कसे वाचता येइल…?

float * (* (*ptr)(int))(double **,char c)

  1. ptr is a pointer
  2. to a function that takes as parameter an int,
  3. and returns a pointer
  4. to a function that takes as parameters a pointer to pointer to double and a char,
  5. and returns a pointer to float.

इथे अजुन एक complex declaration कसे वाचता येइल पाहू. हे मी स्टॅक-ओव्हरफ्लो वरून घेतले आहे. रुल्स कसे पाळले आहेत ते फक्त पहा…

int * (* (*fp1) (int) ) [10];

  1. व्हेअरेबल नेम पासून सुरवात करा ————————– fp1
  2. उजव्या बाजूला जा परंतू फक्त ब्रॅकेट ) आहे म्हणून डावीकडे जा जिथे * आहे ————– is a pointer
  3. ब्रॅकेट्स च्या जोडी बाहेर आला की (int) भेटेल ——— to a function that takes an int as argument
  4. पुन्हा डावीकडे जा, ज्या ठिकाणी * भेटत्प —————————————- and returns a pointer
  5. पुन्हा ब्रॅकेट्स च्या बाहेर जा व उजवीकडे तुम्हाला [10] भेटेल ——– to an array of 10
  6. पुन्हा डावीकडे जा तुम्हाला * भेटतो —————————————– pointers to
  7. उजवीकडे गेला तर ; भेटतो म्हणुन पुन्हा डावीकडॆ जा, तुम्हाला int भेटेल ——————————– int.

 

कधी कधी C language मधील const हा modifier सुद्धा डिक्लेरेशन स्टेटमेंट मध्ये तुम्हाला दिसेल व अजून गोंधळ वाढवेल. जसे की

const char **ptr;

हे वाचायचे असेल तर ते ptr is a pointer to pointer to const char असे लिहीता येइल.

या ठिकाणी const या शब्दाची position सुद्धा महत्वाची असते जसे की

char ** const ptr; असे असले तर मात्र ते ptr is a constant pointer to pointer to char असे वाचावे लागेल.

अशीच काही डिक्लेरेशन्स मी खाली अभ्यासा साठी देत आहे. नाही कळाले तर मला कळवा. मी सविस्तर पद्धतीने तुम्हाला सांगेन समजावून.

  1. int i;                                               i is an int
  2. int *p;                                            p is an int pointer (p is pointer to an int)
  3. int a[ ];                                          a is an array of int
  4. int f( );                                           f is a function returning an int
  5. int **pp;                                       pp is a pointer to an int pointer (pp is pointer to a pointer to an int)
  6. int (*pa)[ ];                                  pa is a pointer to an array of int
  7. int (*pf)( );                                   pf is a pointer to a function returning an int
  8. int *ap[ ];                                     an array of integer pointers (ap is an array of pointers to int)
  9. int aa[ ][ ];                                   aa is an array of arrays of int
  10. int *fp( );                                      fp a function returning a pointer of type int
  11. int ***ppp;                                  ppp is a pointer to a pointer to a pointer of type int
  12. int (**ppa)[ ];                             ppa is a pointer to a pointer to an array of int
  13. int (**ppf)( );                              ppf is a pointer to a pointer to a function returning an int
  14. int *(*pap)[ ];                             pap is a pointer to an array of pointers having type int
  15. int (*paa)[ ][ ];                           ppa is a pointer to an array of arrays of int
  16. int *(*pfp)( );                              pfp is a pointer to a function returning a pointer of type int
  17. int **app[ ];                                app is an array of pointers to pointers of type int
  18. int (*apa[ ])[ ];                           apa is an array of pointers to arrays of int
  19. int (*apf[ ])( );                            apf is an array of pointers to functions returning an int
  20. int *aap[ ][ ];                              aap is an array of arrays of pointers having type as int
  21. int aaa[ ][ ][ ];                            aaa is an array of arrays of arrays of int
  22. int **fpp( );                                 fpp is a function returning a pointer to a pointer of type int
  23. int (*fpa( ))[ ];                            fpa is a function returning a pointer to an array of int
  24. int (*fpf( ))( );                             fpf  is a function returning a pointer to a function returning an int

गंम्मत म्हणजे कोणा एका अवलियाने एक ऑनलाइन aaplication ठेवले आहे. http://cdecl.org या वेबसाइटवर तुम्हाला हे मिळेल. त्यामुळे वर दिलेली डिक्लेरेशन्स तुम्हाला पडताळून पहायची असतील तर हे tool वापरायला हरकत नाही.

Leave a Reply