2011-08-31 8 views
7
FUNC(param); 

जब paramchar * है, func_string पर प्रेषित करें।सी में एक सामान्य मैक्रो कैसे कार्यान्वित करें?

जब यह func_int

मैं इस के लिए एक समाधान है, वहाँ हो सकता है के रूप में चर प्रकार संकलन समय पर जाना जाता है सोचने के लिए int, प्रेषण है ..

+0

यहां तक ​​कि यदि यह संभव था, तो यह बेहद खराब होगा। सी इसके लिए डिजाइन नहीं किया गया था। Structs और यूनियनों का प्रयोग करें, आप इस तरह से रन-टाइम प्रेषण भी प्राप्त कर सकते हैं। –

उत्तर

10

चर प्रकार संकलक के लिए जाना जाता है, लेकिन करने के लिए नहीं प्रीप्रोसेसर (जो कोड को असंगठित पाठ टोकन की एक धारा के रूप में देखता है, और इसमें केवल सरल प्रतिस्थापन संचालन करता है)। तो मुझे डर है कि आप इसे सी मैक्रोज़ के साथ प्राप्त नहीं कर सकते हैं।

सी ++ में, उन्होंने ऐसी समस्याओं को हल करने के लिए टेम्पलेट का आविष्कार किया (और अधिक)।

+0

क्या ** सी ** में कोई काम है? – lexer

+2

यह एक झूठा निष्कर्ष है। प्रीप्रोसेसर को तर्क प्रकारों को जानने की आवश्यकता नहीं है, यदि आप मैक्रो विस्तार की व्यवस्था कर सकते हैं ताकि * कंपाइलर * विश्लेषण कर सके। Gnu compiler के लिए इसे हल करने के लिए arnaud576875 का उत्तर देखें। साथ ही, प्रीप्रोसेसर कोड को असंगठित पाठ के रूप में नहीं देखता है, लेकिन * टोकन स्ट्रीम * के रूप में, जो एक महत्वपूर्ण अंतर है। –

1

आप इसे मैक्रो के साथ नहीं कर सकते हैं। मैक्रो का मूल्य संकलन समय पर प्रतिस्थापित किया जाता है और इसका इरादा नहीं किया जाता है। वे सिर्फ विकल्प हैं।

11

यह C1X के साथ संभव होगा लेकिन वर्तमान मानक में नहीं।

यह इस तरह दिखेगा:

#define cbrt(X) _Generic((X), long double: cbrtl, \ 
          default: cbrt, \ 
          float: cbrtf)(X) 
+0

चूंकि यह प्रश्न Google पर पहले पॉप अप करता है: यह अब सी 11 का उपयोग कर संभव है http://en.cppreference.com/w/c/language/generic –

4

वहाँ C89/एएनएसआई सी में समय की जांच प्रकार चलाने के लिए कोई संभावना नहीं है, लेकिन वहाँ जो यह अनुमति देता है जीसीसी के लिए एक विस्तार है। अगर मुझे याद है तो टाइप लाइन या उन पंक्तियों के साथ कुछ। मैंने इसे एक बार लिनक्स कर्नेल में देखा था।

kernel.h में:

#define min(x, y) ({    \ 
typeof(x) _min1 = (x);   \ 
typeof(y) _min2 = (y);   \ 
(void) (&_min1 == &_min2);  \ 
_min1 < _min2 ? _min1 : _min2; }) 

इस लेख पर एक नज़र डालें: जब मैं पहली बार देखा था इस मैं वास्तव में यहाँ पर एक प्रश्न पूछा GCC hacks in the Linux kernel

एसओ के बारे में:

min macro in kernel.h

मुझे पूरा यकीन नहीं है कि आप अपनी समस्या का समाधान करने के लिए इसका उपयोग कैसे करेंगे, लेकिन यह देखने के लायक कुछ है टी।

+0

यह रनटाइम प्रकार की जांच नहीं है - क्योंकि सी गतिशील रूप से टाइप नहीं किया गया है, प्रकार जानकारी केवल संकलन-समय – Christoph

1

परिवर्तनीय प्रकार वास्तव में संकलन समय पर ज्ञात हैं, हालांकि संकलन से पहले मैक्रो विस्तार होता है। मेरा सुझाव है कि आप एक मैक्रो के बजाय 2 अधिभारित कार्यों को लागू करें।

5

आप प्रकार की विशेषताओं के लिए परीक्षण कर सकते हैं।

उदाहरण के लिए, int नकारात्मक मान रख सकता है, जबकि char* नहीं कर सकता। तो अगर ((typeof(param))-1) < 0, param अहस्ताक्षरित है:

if (((typeof(param))-1) < 0) { 
    do_something_with_int(); 
} else { 
    do_something_with_char_p(); 
} 

संकलक स्पष्ट रूप से यह बाहर का अनुकूलन।

इसे यहाँ का प्रयास करें: http://ideone.com/et0v1

यह और भी आसान है, तो प्रकार विभिन्न आकारों था होगा।उदाहरण के लिए, अगर आप चाहते हैं एक सामान्य मैक्रो लिखने के लिए की तुलना में अलग चरित्र आकार संभाल कर सकते हैं:

if (__builtin_types_compatible_p(typeof(param), int)) { 
    func_int(param); 
} else if (__builtin_types_compatible_p(typeof(param), char*)) { 
    func_string(param); 
} 

यह प्रयास करें:

if (sizeof(param) == sizeof(char)) { 
    /* ... */ 
} else if (sizeof(param) == sizeof(char16_t)) { 
    /* ... */ 
} else if (sizeof(param) == sizeof(char32_t)) { 
    /* ... */ 
} else { 
    assert("incompatible type" && 0); 
} 

जीसीसी एक __builtin_types_compatible_p() builtin समारोह है कि प्रकार संगतता के लिए जाँच कर सकते हैं यहां: http://ideone.com/lEmYE

आप इसे करने के लिए जो प्रयास कर रहे हैं उसे प्राप्त करने के लिए आप इसे मैक्रो में डाल सकते हैं:

#define FUNC(param) ({            \ 
    if (__builtin_types_compatible_p(typeof(param), int)) {   \ 
     func_int(param);            \ 
    } else if (__builtin_types_compatible_p(typeof(param), char*)) { \ 
     func_string(param);           \ 
    }                 \ 
}) 

(({...})GCC's statement expression है, यह बयानों के समूह को एक रैल्यू होने की अनुमति देता है।

__builtin_choose_expr() बिल्टिन संकलन करने के लिए अभिव्यक्ति का चयन कर सकते हैं।

#define FUNC(param)              \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \ 
     , func_int(param)             \ 
     , __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \ 
      , func_string(param)           \ 
      , /* The void expression results in a compile-time error  \ 
       when assigning the result to something. */    \ 
      ((void)0)              \ 
     )                 \ 
    ) 

यह वास्तव में से एक थोड़ा संशोधित उदाहरण है (इस मामले में somehting अमान्य संकलन के द्वारा): __builtin_types_compatible_p के साथ इस करता है, तो परम के प्रकार दोनों int और char* साथ संगत नहीं है संकलन समय पर एक त्रुटि को गति प्रदान करने की अनुमति देता है __builtin_choose_expr docs

+0

'func_int (x); ',' func_string (x); 'पर उपलब्ध है और पूरी चीज को' do {} के अंदर रखें (0)' –

+0

मैंने मूल रूप से कोड को संलग्न नहीं किया 'do {} जबकि()' क्योंकि यह मैक्रो नहीं था ;-) – arnaud576875

+2

-1 'टाइपोफ़' सी नहीं है बल्कि एक जीसीसी एक्सटेंशन भी है। आपको क्या लगता है कि किसी पते में 'साइन' बिट सेट नहीं हो सकता है? –

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