एक PROTOTYPE मैक्रो का क्या मतलब है जो केवल इसके तर्कों तक फैलता है?


82

मेरे पास एक हेडर फ़ाइल है जिसमें सम्‍मिलित है

#define PROTOTYPE(s) s

उसका क्या अर्थ? ऐसा लगता है कि यह सिर्फ इनपुट को खुद से बदल देगा।

इसके चारों ओर अन्य निर्देशों के टन हैं, लेकिन केवल एक ही असर होता है जो किसी भी असर की जाँच करता है अगर यह परिभाषित किया गया है #ifndef PROTOTYPE:। मुझे HDF4 हेडर फ़ाइलों में कुछ स्थान मिले जो ऐसा करते हैं #define PROTOTYPE:। इसलिए, इनमें से कोई भी मेरे सवाल को स्पष्ट नहीं करता है। अभी भी बहुत बेकार लगता है।

यहाँ इसका उपयोग कैसे किया जाता है:

CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));

यह एक प्रोजेक्ट का हिस्सा है जो Sybase Open Client का उपयोग करता है। clientmsg_callback का उपयोग बाद में यहाँ किया जाता है:

ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
                  (CS_VOID *)clientmsg_callback);

मैं यहाँ से एक नमूना कार्यक्रम से जा रहा हूँ:

http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc35570.1570/html/clcprgde/clcprgde10.htm

clientmsg_callback को बाद में लागू किया गया है। मुझे लगता है कि नमूना मूल रूप से C + के बजाय C को ध्यान में रखकर लिखा गया था। शायद इसके साथ कुछ करना है?


6
क्या पास #if/ #ifdef/ #ifndef/ #elseनिर्देश हैं जहां इसकी बजाय एक अलग परिभाषा हो सकती है? यह अन्य मैक्रोज़ में उपयोग किए जाने पर विशेष रूप से #या पास में अंतर कर सकता है ##। यह सिर्फ एक टिप्पणी शैली के लिए हो सकता है। वास्तव में जवाब देने के लिए पर्याप्त संदर्भ नहीं।
21

एक सामान्य उत्तर के रूप में: क्योंकि किसी को बदलने का इच्छुक होना चाहिए PROTOTYPE। यदि आप कोड में अजीब परिभाषित करते हैं जो बेकार लगते हैं, तो संभावित लचीलेपन के बारे में सोचें यदि कोई व्यक्ति आसानी से कुछ बदलना चाहता है।
अपोलिस, मोनिका से

जवाबों:


130

पुराने दिनों में वापस, वास्तव में शुरुआती सी, एक प्रोटोटाइप जैसी कोई चीज नहीं थी। फ़ंक्शन की कोष्ठक के बाद फ़ंक्शन तर्क सूची इस तरह से आई :

square(x)
int x;
{
int y = x * x;
return y;
}

इन दिनों, निश्चित रूप से, तर्क कोष्ठक के अंदर जाते हैं:

square(int x)
{
int y = x * x;
return y;
}

"लापता" रिटर्न प्रकार पर ध्यान दें; सी फ़ंक्शंस का उपयोग स्पष्ट रूप से वापसी के लिए किया जाता intथा, और यह केवल तभी होता था जब आपको एक अलग रिटर्न प्रकार की आवश्यकता होती थी जो आपको यह कहना था कि यह क्या था।

समारोह घोषणाओं में अभी तक नियमों का एक और सेट था। K & R C (प्राचीन संस्करण) में एक फ़ंक्शन घोषणा में कोई तर्क नहीं था:

int square();

और ANSI C में फ़ंक्शन प्रोटोटाइप में तर्कों की एक सूची है:

int square(int x);

संक्रमण के दौरान, लोगों ने निराला मैक्रोज़ का इस्तेमाल किया ताकि वे दोनों तरीकों को संकलित कर सकें:

int square(PROTOTYPE(int x));

साथ में

#define PROTOTYPE(s)

इसका विस्तार पहले संस्करण में होगा।

साथ में

#define PROTOTYPE(s) s

इसका विस्तार दूसरे तक होगा।

प्रश्न में कोड में "अतिरिक्त" कोष्ठक के संबंध में, तर्क सूची में एक से अधिक तर्क होने पर उनकी आवश्यकता होती है। उनके बिना, मैक्रो इनवोकेशन में एक से अधिक तर्क होते हैं, इसलिए केवल एक तर्क के साथ परिभाषित मैक्रो से मेल नहीं होगा:

PROTOTYPE(int x, int y)   // error: too many arguments
PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)

10
वाह। अतीत से विस्फोट। सॉफ्टवेयर में मेरी पहली नौकरी में से एक मौजूदा कोड बेस से यह सामान निकाल रहा था। एक लाइनर पाठ-उत्परिवर्तन कार्यक्रमों के यूनिक्स की सरणी के लिए एक स्वस्थ सम्मान बनाया।
user4581301

15
मुझे समझ में नहीं आ रहा है कि उन कामों को कैसे परिभाषित किया जाता है #define PROTOTYPE(s), इनपुट के साथ कैसे int x;बदल जाता है x? ऐसा लग रहा है कि यह मेरे लिए एक खाली स्ट्रिंग को लपेटता है
फेरीबग

3
@Ferrybig - क्षमा करें, मैंने चीजों को भ्रमित किया। यह प्रोटोटाइप है जो इस तरह से परिभाषित होता है। के एंड आर सी में, एक प्रोटोटाइप में कोई तर्क नहीं था, और एएनएसआई सी में यह तर्क सूची की शैली है जिसे हम देखने के लिए उपयोग कर रहे हैं।
पीट बेकर

1
इस प्रथा zlib.hको OF()मैक्रो के साथ zlib लाइब्रेरी के हेडर में भी देखा जा सकता है : github.com/madler/zlib/blob/master/zlib.h
पॉल बेलांगर

@PaulBelanger वास्तविक परिभाषा में है zconf.h
एसएस ऐनी

16

कुछ इस तरह की अनुमति देने के लिए मैक्रो का उपयोग हेडर फ़ाइल में प्रोटोटाइप में किया जाएगा:

int foo PROTOTYPE((int bar));

यदि ANSI C का पता लगाया गया था ( __STDC__1 के रूप में परिभाषित), तो इसका विस्तार होगा:

int foo(int bar);

यदि ANSI C का पता नहीं लगाया गया है, तो इसका विस्तार होगा:

int foo();

सी के मानकीकरण से पहले जो आम था।

कुछ पुस्तकालय अभी भी ऐसा करते हैं; यदि आप देखते हैं tcpd.h(यदि आपके पास उपलब्ध है), तो आप देखेंगे:

/* someone else may have defined this */
#undef  __P

/* use prototypes if we have an ANSI C compiler or are using C++ */
#if defined(__STDC__) || defined(__cplusplus)
#define __P(args)       args
#else
#define __P(args)       ()
#endif

यह इसे अच्छी तरह से समझाता है।

डबल कोष्ठक के रूप में, __P(arg1, arg2)एक सिंटैक्स त्रुटि देगा (मैक्रो के लिए बहुत से तर्क पास कर रहा है), जबकि __P((arg1, arg2))ठीक होगा (केवल कोष्ठक में संलग्न)।

यह __extension__((...))जीएनयू सी में समान है । गैर-जीएनयू संकलक में, बस #define __extension__(unused)अर्ध-पोर्टेबल कोड है, जैसा कि सिर्फ एक "तर्क" दिया जाता है, कोष्ठक में लपेटा जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.