2011-10-03 8 views
7

gnu's C पर प्रलेखन बताता है कि यदि फ़ंक्शन में __attribute__((sentinel)) है तो इसमें फ़ंक्शन के अंतिम तर्क के रूप में NULL होना चाहिए।कस्टम प्रेषित मूल्य के साथ एक वैरैडिक फ़ंक्शन कैसे बनाएं?

क्या तर्क सूची समाप्त करने के लिए मार्कर के रूप में कोई अन्य मूल्य होना संभव है?

+1

जहां तक ​​कोई फ़ंक्शन बनाते हैं, स्पष्ट रूप से आप इसे _can_ करते हैं। मुझे यह जांचने के लिए किसी भी जीएनयू सीमाओं के बारे में पता नहीं है कि तर्क मनमानी varargs योजनाओं के लिए सही हैं। उनके पास पैरामीटर को "गिनती" के रूप में चिह्नित करने के लिए एक विशेषता भी नहीं है कि कितने तर्क दिए गए थे ताकि संकलक जांच सके कि उन्हें सही मिला है या नहीं। –

उत्तर

3

आप तर्क सूची के अंत को चिह्नित करने के लिए इच्छित मूल्य का उपयोग कर सकते हैं, बशर्ते आप तर्क सूची से इसे प्राप्त करने के बारे में पर्याप्त जानकारी दें। संकलक सामान्य रूप से जांच नहीं करेगा कि आपके द्वारा चुने गए मान को वास्तव में पारित किया जाता है जब फ़ंक्शन कहा जाता है, इसलिए आपको इसकी देखभाल करने की आवश्यकता होगी।

अनिवार्य रूप से आप सामान्य तरीके से एक भिन्न कार्य बनाते हैं, और फ़ंक्शन के अंदर आप अपने प्रेषण से मेल खाने वाले किसी व्यक्ति को पढ़ते समय तर्क पढ़ना बंद कर देते हैं - विशेष रूप से कुछ भी करने के लिए विशेष नहीं है, लेकिन आपको यह जानने की आवश्यकता है कि किस प्रकार के पढ़ने के लिए तर्क।

उदाहरण के लिए:

#include <stdarg.h> 

/* Count arguments up to the number 5 */ 
int countArgsTilFive(int first, ...) 
{ 
    int res = 1; 
    va_list ap; 
    if (first == 5) return 0; 
    va_start(ap,first); 
    while (va_arg(ap,int) != 5) res++; 
    va_end(ap); 
    return res; 
} 

... अपने सभी तर्क है कि 5 से पहले होने की गणना होती है। यदि आप सूची में कहीं भी 5 पास नहीं करते हैं, या यदि आप इसे तर्क देते हैं जो int नहीं हैं तो खराब चीजें हो सकती हैं।

संकेत दिए गए है, जहां एक प्रहरी नोड पिछले, तर्क के रूप में पहले के रूप में पारित हो जाता है, और फिर से साथ एक और उदाहरण:

/* Count arguments, excluding the first, until the first occurs again */ 
int countPtrs(void *sentinel, ...) 
{ 
    int res = 0; 
    va_list ap; 
    va_start(ap,sentinel); 
    while (va_arg(ap,void *) != sentinel) res++; 
    va_end(ap); 
    return res; 
} 
+1

जीसीसी के '__attribute __ ((सेंटीनेल) के साथ) 'कंपाइलर _can_ जांचें कि तर्क सूची दिए गए मान के साथ समाप्त होती है। यह सिर्फ इतना है कि यह केवल एकमात्र मूल्य है 'NULL' - यह आपको संकलक को सत्यापित करने के लिए एक और मूल्य नहीं चुनने देता है। –

+1

यदि वह सिर्फ जानना चाहता है कि मनमाने ढंग से भेजे गए मानों के लिए '__attribute __ ((सेंटीनेल)) कुछ है, तो उत्तर इतना उपयोगी नहीं है .. लेकिन अगर' __attribute __ ((सेंटीनेल) के बारे में सामान 'इंप्रेशन छोड़ दिया गया है कि गैर-न्यूल प्रेषितों का बिल्कुल उपयोग नहीं किया जा सका, इसे साफ़ करना चाहिए। – Dmitri

0

यह वह जगह है (के एक संपादित डाउन संस्करण) कैसे एप्पल को परिभाषित करता है काम NS_REQUIRES_NIL_TERMINATION पूर्व संकलन जांच, यानी कुछ विधि के साथ एक शून्य प्रहरी की आवश्यकता होती है ...

+ (NSArray*)arrayWithRects:(NSR)rect,...NS_REQUIRES_NIL_TERMINATION;

#if !defined(NS_REQUIRES_NIL_TERMINATION) 
#if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549) 
    #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1))) 
#else 
    #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel)) 
#endif 
#endif 

नहीं काफी यकीन है कि क्या differenc ई उन दो संकलक निर्देशों के बीच है .. लेकिन मुझे लगता है कि इस निर्माण का उपयोग "अन्य", "कस्टम" सेंटीनेल के साथ किया जा सकता है .. मैं NSNotFound - XX_REQUIRES_NSNOTFOUND_TERMINATION या उसके जैसा कुछ सोच रहा हूं?

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^