इस ट्यूटोरियल में, आपको c प्रीप्रोसेसरों से परिचित कराया जाएगा, और आप उदाहरणों की मदद से #include, #define और कंडीशनल कंपाइलेशन का उपयोग करना सीखेंगे।
C में प्रीप्रोसेसर क्या है ?
सी प्रीप्रोसेसर एक मैक्रो प्रीप्रोसेसर है (आपको मैक्रोज़ को परिभाषित करने की अनुमति देता है) जो आपके प्रोग्राम को संकलित करने से पहले बदल देता है। ये परिवर्तन हेडर फ़ाइल, (header file) मैक्रो विस्तार (macro expansions) आदि का समावेश हो सकते हैं।
सी प्रीप्रोसेसर की विशेषताएं(Features of C Preprocessor)
C प्रोग्राम को ‘Source Code’ के नाम से जाना जाता है। जब स्रोत कोड ‘प्रीप्रोसेसर’ के माध्यम से पारित किया जाता है, तो यह ‘Source Code’ में प्रयुक्त प्रीप्रोसेसर निर्देशों के अनुसार ”Extended Source Code” बनाता है। प्रत्येक प्रीप्रोसेसर निर्देश # symbol से शुरू होता है। Source code में निम्नलिखित प्रीप्रोसेसर निर्देशों का उपयोग किया जा सकता है।
(a) Macro expansion
(b) File Inclusion
(c) Conditional compilation
(d) Miscellaneous directives
सभी प्रीप्रोसेसिंग निर्देश # symbol से शुरू होते हैं। उदाहरण के लिए, आइए एक-एक करके इन प्रीप्रोसेसर निर्देशों को समझते हैं।
(a) Macro expansion
मैक्रोज़ को छोटे फ़ंक्शन के रूप में कहा जा सकता है जो प्रक्रिया के लिए ओवरहेड नहीं हैं। यदि हमें एक फ़ंक्शन (एक छोटी परिभाषा वाला) लिखना है जिसे रिकर्सिवली (बार-बार) कॉल करने की आवश्यकता है, तो हमें फ़ंक्शन पर मैक्रो पसंद करना चाहिए।
तो, इन मैक्रोज़ को परिभाषित करना प्रीप्रोसेसर द्वारा किया जाता है।
#define SI 1000
मैक्रोज़ दो प्रकार के होते हैं:-
ऑब्जेक्ट-लाइक (पैरामीटर नही लेते)
और फंक्शन-लाइक (पैरामीटर ले सकते हैं)
// object-like macro
#define
// function-like macro
#define ()
आप #undef के साथ मैक्रो परिभाषा हटा सकते हैं|
// delete the macro
# undef
मैक्रो का एक सरल उदाहरण है।
# include<stdio.h>
#define pi 3.1428
int main()
{
float r =6.25,area;
area =pi*r*r;
printf("Area of cirle=%f\n",area);
return 0;
}
Output:-
# define pi 3.1428
(b) File inclusion
पुस्तकालय(library) से सभी फाइलों सहित जो हमारे program की जरूरत है। एचएलएल (High Level Language) में हम #include लिखते हैं जो प्रीप्रोसेसर के लिए एक निर्देश है जो इसे निर्दिष्ट लाइब्रेरी फ़ाइल की सामग्री को शामिल करने के लिए कहता है। उदाहरण के लिए, #include प्रीप्रोसेसर को लाइब्रेरी फ़ाइल stdio.h में सभी सामग्री शामिल करने के लिए कहेगा।
इसे दोहरे उद्धरण चिह्नों का उपयोग करके भी लिखा जा सकता है –
#include “stdio.h”
नोट: यदि फ़ाइल नाम enclosed के भीतर brackets है, तो फ़ाइल को Standard compiler में खोजा जाता है जिसमें पथ शामिल हैं। यदि फ़ाइल नाम दोहरे उद्धरण चिह्नों में संलग्न है, तो वर्तमान स्रोत निर्देशिका को शामिल करने के लिए खोज पथ का विस्तार किया गया है।
(c) Conditional compilation
यदि हम चाहें, तो हम कंपाइलर को प्रीप्रोसेसिंग कमांड #ifdef और #endif को सम्मिलित करके सोर्स कोड के हिस्से को छोड़ सकते हैं, जिनका सामान्य रूप नीचे दिया गया है।
#ifdef marcroname
Statement 1;
Statement 2;
Statement 3;
#endif
यदि मैक्रोनाम को # परिभाषित किया गया है, तो कोड के ब्लॉक को हमेशा की तरह संसाधित किया जाएगा, अन्यथा नहीं।
#ifdef कहाँ उपयोगी होगा? आप अपने प्रोग्राम का केवल एक भाग कब संकलित करना चाहेंगे? तीन मामलों में, नीचे चर्चा की गई।
(a) कोड की कुछ पंक्तियों को “comment out” करने के लिए जिनकी हमें अभी आवश्यकता नहीं है जैसा कि नीचे दिखाया गया है।
Int main ()
{
# ifdef NOTENOW
Statement 1;
Statement 2;
# endif
Statement 3;
Statement 4;
}
यहां, स्टेटमेंट 1 और 2 तभी संकलित होंगे जब मैक्रो नोटो को परिभाषित किया गया हो, और हमने उद्देश्यपूर्ण रूप से इस मैक्रो की परिभाषा को छोड़ दिया है। बाद की तारीख में, यदि हम चाहते हैं कि इन स्टेटमेंटो को भी संकलित (compiled) किया जाए, तो हम #ifdef और #endif स्टेटमेंटों को हटा सकते हैं या सबसे ऊपर #define notnow कर सकते हैं।
(b) #ifdef का एक अधिक परिष्कृत उपयोग प्रोग्राम को पोर्टेबल बनाने के साथ करना है, अर्थात, उन्हें अलग-अलग कॉन्फ़िगरेशन वाले दो कंप्यूटरों पर काम करना है। आप कोड की पंक्तियों को अलग करके ऐसा कर सकते हैं जो प्रत्येक मशीन के लिए अलग-अलग होनी चाहिए, उन्हें #ifdef के साथ चिह्नित करके निम्नानुसार किया जा सकता है।
Int main ( )
{
#ifdef INTEL
Code suitable for an Intel PC
#else
Code suitable for a Motorola PC
# endif
Code common to both the computers
}
जब हम इस प्रोग्राम को compile करते हैं, तो यह केवल मोटोटोला पीसी के लिए उपयुक्त कोड और सामान्य कोड को compile करेगा क्योंकि मैक्रो इंटेल को परिभाषित नहीं किया गया है। अगर हम प्रोग्राम को एक इंटेल पीसी पर चलाना चाहते हैं, तो प्रोग्राम को फिर से कंपाइल करने से पहले हमें शीर्ष (top) पर एक स्टेटमेंट जोड़ना होगा|
# define INTEL
कभी-कभी, #ifdef के बजाय, #ifndef निर्देश का उपयोग किया जाता है। #ifdef (जिसका अर्थ है ‘यदि परिभाषित नहीं है’) #ifdef के बिल्कुल विपरीत काम करता है।
(C)आदर्श रूप से, हमें किसी फ़ाइल को केवल एक बार #include करना चाहिए। लेकिन अगर गलती से हम इसे दो बार शामिल कर लेते हैं, तो इसे केवल एक बार शामिल किया जाना चाहिए। इसे #ifndef का उपयोग करके प्राप्त किया जा सकता है जैसा कि नीचे दिखाया गया है।
/*Myfile.h*/
#ifndef_myfile_h
#define_myfile_h
/*Some declarations */
#endif
पहली बार फ़ाइल ‘myfile.h’ शामिल (include) हो जाती है, प्रीप्रोसेसर जांचता (check) है कि _myfile_h नामक मैक्रो को परिभाषित किया गया है या नहीं। यदि यह नहीं किया गया है, तो यह परिभाषित हो जाता है और शेष कोड शामिल हो जाता है क्योंकि _myfile_h पहले से ही परिभाषित है।
#if and #elif Directives
#if निर्देश का उपयोग यह जांचने के लिए किया जा सकता है कि कोई व्यंजक गैर-शून्य मान का मूल्यांकन (expression evaluating to a non-zero value) करता है या नहीं। यदि expression का परिणाम non-zero है, तो #else, #elif या #endif तक की बाद की पंक्तियों को कंपाइल किया जाता है, अन्यथा उन्हें छोड़ दिया जाता है। #if निर्देश का एक सरल उदाहरण नीचे दिखाया गया है।
Int main ( )
{
#if TEST <=5
Statement 1 ;
# else
Statement 2 ;
# endif
}
यदि एक्सप्रेशन, TEST <=5 मूल्यांकन सत्य है, तो स्टेटमेंट 1 कंपाइल किया जाता है, अन्यथा स्टेटमेंट 2 कंपाइल किया जाता है। एक्सप्रेशन टेस्ट <= 5 के स्थान पर, अन्य एक्सप्रेशन जैसे (LEVEL == High || LEVEL == LOW ) या ADAPTER == SVGA का भी उपयोग किया जा सकता है। यदि आवश्यक हो, तो हम नेस्टेड कंडीशनल कंपीलेशन का भी उपयोग कर सकते हैं।
(d) Miscellaneous directives
दो और प्रीप्रोसेसर निर्देश उपलब्ध हैं, हालांकि उनका आमतौर पर उपयोग नहीं किया जाता है।
(a) #undef
(b) #pragma
(a) #undef Directive
कुछ अवसरों पर, यह वांछनीय(desirable)हो सकता है| कि एक परिभाषित नाम ‘undefined’ हो जाए। इसे #undef निर्देश के माध्यम से पूरा किया जा सकता है जैसा कि नीचे दिखाया गया है।
#undef PENTIUM
इससे PENTIUM की परिभाषा हटा दी जाएगी। बाद के सभी #ifdef PENTIUM स्टेटमेंट असत्य का मूल्यांकन करेंगे। प्रेक्टिस में, शायद ही कभी आपको किसी मैक्रो को अपरिभाषित करने की आवश्यकता होती है, लेकिन यदि आपको इसकी आवश्यकता होती है, तो आप जानते हैं कि पीछे हटने के लिए कुछ है।
(b) #pragma Directive
इस निर्देश का उपयोग कुछ सुविधाओं को चालू या बंद करने के लिए किया जाता है। Pragma एक निर्माण उपकरण से दूसरे में भिन्न होता है। कुछ pragma source list को स्वरूपित करने और ऑब्जेक्ट फ़ाइल में टिप्पणियां रखने से संबंधित हैं। कुछ अन्य हैं जो हमें कंपीलर द्वारा उत्पन्न चेतावनियों को दबाने की अनुमति देते हैं। इनमें से कुछ प्रज्ञाओं की चर्चा नीचे की गई है।
(a) #pragma startup और #pragma exit: ये निर्देश हमें उन कार्यों को निर्दिष्ट करने की अनुमति देते हैं| जिन्हें प्रोग्राम स्टार्टअप (before main ()) या प्रोग्राम निकास (कार्यक्रम समाप्त होने से ठीक पहले) पर कॉल किया जाता है। उनका उपयोग इस प्रकार होता है|
#include <stdio.h>
void fun1();
void fun2();
#pragina startup fun1
#pragma exit fun2
int main()
{
printf ("Inside main\n");
return 0;
}
void fun1()
{
printf("Inside fun1\n")
}
void fun2()
{
Printf (" inside fun2\n");
}
Output :-
Inside fun 1
Inside main
Inside fun 2
(b) #pragma warn: Compilation पर कंपाइलर प्रोग्राम में errors और warnings की रिपोर्ट करता है, यदि कोई हो। errors को सुधारना होगा। दूसरी ओर, चेतावनियाँ प्रोग्रामर को एक संकेत या सुझाव देती हैं कि कोड के किसी विशेष भाग में कुछ गड़बड़ हो सकती है। चेतावनियां प्रदर्शित होने पर दो सबसे आम स्थितियां इस प्रकार हैं।
•यदि आपने कोड लिखा है जिसे खराब प्रोग्रामिंग अभ्यास माना जाता है। उदाहरण के लिए, यदि कोई फ़ंक्शन कोई वैल्यू नहीं लौटाता है और आपने इस फ़ंक्शन के रिटर्न प्रकार को शून्य घोषित नहीं किया है।
•यदि आपके पास कोड लिखा है जो रन-टाइम errors का कारण बन सकता है, जैसे कि एक प्रारंभिक सूचक को मान निर्दिष्ट करना।
#pragma warn निर्देश कंपाइलर को बताता है कि हम किसी विशिष्ट चेतावनी को दबाना चाहते हैं या नहीं। इस pragma का उपयोग नीचे दिखाया गया है।
#include <stdio.h>
#pragma warn -rvl /*return value */
#pragma warn -par /* parameter not used */
#pragma warn - rch /* unreasonable code */
Int F1 ()
{
Int a= 5;
}
Void F2 (int x )
{
Printf ("inside f2\n");
}
Int f3()
{
Int x= 6;
Return x ;
X++ ;
}
F1();
F2(7);
f3() ;
Return 0;
}
यदि आप प्रोग्राम का अध्ययन करते हैं, तो आप तुरंत तीन समस्याओं को नोटिस कर सकते हैं। य़े हैं:-
(a) हालांकि वादा किया गया है, f1() एक मूल्य वापस नहीं करता है।
(b) f2() को पारित पैरामीटर x कहीं भी उपयोग नहीं किया जा रहा है।
(c) f3() में नियंत्रण (control) कभी भी x++ तक नहीं पहुंच सकता है।
यदि हम प्रोग्राम को कंपाइल करते हैं, तो हमें उपरोक्त समस्याओं का संकेत देने वाली चेतावनियों की अपेक्षा करनी चाहिए। हालाँकि, ऐसा नहीं होता है क्योंकि हमने #pragma निर्देशों का उपयोग करके चेतावनियों को दबा दिया है।
यदि हम चिह्न को ‘+’ से बदल देते हैं, तो ये चेतावनियां कंपिलेशन पर फ्लैश हो जाएंगी। हालांकि चेतावनियों को दबाना एक बुरी आदत है, लेकिन कभी-कभी उन्हें दबाना उपयोगी हो जाता है। उदाहरण के लिए, एक बड़े प्रोग्राम को कंपाइल करते समय आप पहले सभी errors को समाप्त करना चाहते हैं और फिर अपना ध्यान चेतावनियों की ओर मोड़ सकते हैं। ऐसे समय में, आप चेतावनियों को दबा सकते हैं। एक बार जब आप सभी errors को समाप्त कर देते हैं, तो आप चेतावनियों को चालू कर सकते हैं और उन पर ध्यान दे सकते हैं।
चलिए कुछ प्रोग्रामिंग प्रैक्टिस हो जाये |
The build process :-
एक सी प्रोग्राम को एक्जीक्यूटेबल फॉर्म में बदलने में कई चरण शामिल हैं। चित्र 12.1 प्रत्येक चरण के दौरान बनाई गई फाइलों के साथ इन विभिन्न चरणों को दिखाता है। कई सॉफ्टवेयर डेवलपमेंट टूल्स इनमें से कुछ को हमसे छिपाते हैं। हालाँकि, यदि आप इन चरणों को समझते हैं तो यह आपको एक बेहतर प्रोग्रामर बना देगा।
चित्र 12.2 निर्माण प्रक्रिया के दौरान प्रत्येक प्रोग्राम द्वारा निभाई गई भूमिका को सारांशित करता है।
Program:-
/* Macros ISUPPER, ISLOWER, ISAPLHA, BIG*/
#include <stdio.h>
#define ISUPPER(x) (x>=65 && x<= 90? 1:0)
#define ISLOWER(x) (x>=97 && x <=122 ? 1:0)
#define ISALPHA(x) (ISUPPER(X) || ISLOWER(x))
#define ISALPH(X) ( ISUPPER(X) || ISLOWER(X))
#define BIG(x,y) (x>y?x:y)
int main()
{
char ch;
int d,a,b;
printf ("\nEnter any alphabet/character:");
scanf("%c", &ch);
if ( ISUPPER (ch)==1)
printf("you entered a capital letter\n");
if (ISLOWER (ch)==1)
printf("you entered a small case letter\n");
if(ISALPHA (ch) !=1)
printf("you entered character other than an alphabet\n");
printf("Enter any two numbers:");
scanf("%d%d", &a, &b);
d=BIG(A,B);
printf ("bigger number is %d\n",d);
return 0;
}
Output:-
Enter any alphabet/character:A
You entered a capital letter
Enter any two numbers : 10 20
Bigger number is 20
इस पोस्ट में बस इतना ही हम अगले टॉपिक पर नेक्स्ट पोस्ट में बात करेंगे | c language में, मेने preprocessor in c example तक इस पोस्ट में कवर कर लिया है| जल्द ही हम c language का tutorial पूरा करेंगे और c language पर प्रोग्राम केसे बनाते है| ये भी सिखायेंगे आप साथ ही साथ पुरानी पोस्ट भी पढ़ कर अपना अब्यास जारी रख सकते है| जिससे आपको c language के आने वाले टॉपिक अच्छे से समझ आयेंगे और आपको c language और भी ज्यादा आसान लगेगी | इसी तरह पढ़ते रहे और इस वेबसाइट को follow जरुर कर ले जिससे हमारी आने वाली पोस्ट आप तक सबसे पहले पहुचे|
धन्यवाद |
[…] c language mein preprocessor kya hota hai in hindi, preprocessor in… […]
very hardworking article keep it up