2011-03-28 17 views
10

मैं कुछ इस तरह सी में कोड लिखने के लिए करना चाहते हैं: के बाद सेसी अंदर परिभाषित (मैक्रो) का उपयोग करना अगर बयान

 
if(defined(MACRO)) 
    ... 
else 
    ... 

लेकिन मैं किसी भी तरह से सी में यह करने के लिए नहीं मिल सका परिभाषित (मैक्रो) प्रीप्रोसेसर ऑपरेटर केवल # if के अंदर काम करता है। क्या इसे करने का कोई तरीका है?

मैं वास्तव में क्या करना चाहते क्या लिखना है:

ASSERT(UART, var >= 0);

जहां

 
#define ASSERT(NAME, TEST) \ 
    do { \ 
    if (defined(NAME) && !(TEST)) \ 
     printf("Assert failed"); \ 
    } while(0) 

इस प्रकार मैं, जब एक मैक्रो परिभाषित किया गया है ASSERT चेक पर बदल सकती है और अगर यह परिभाषित नहीं है तो आवेषण की जांच नहीं की जानी चाहिए। यदि आप ऐसा करने की कोशिश करते हैं, तो आपको मिलेगा:

implicit declaration of function `defined'

जो काफी समझा जा सकता है के बाद से जीसीसी संकलक defined() पूर्वप्रक्रमक ऑपरेटर नहीं मिल रहा है।

+1

के संभावित डुप्लिकेट [मैक्रो निर्भर मैक्रो] (http://stackoverflow.com/questions/4927976/macro-dependent-macro) – kennytm

उत्तर

2

क्यों आप बस अलग ढंग से कि मैक्रो के आधार पर ASSERT परिभाषित नहीं करते?

#ifdef MACRO 
#define ASSERT(NAME, TEST) \ 
    do { \ 
     printf("Assert failed"); \ 
    } while(0) 
#else 
#define ASSERT(NAME, TEST) {} 
#endif 

का उपयोग सी सशर्त में तय पूर्वप्रक्रमक मूल्यों से परहेज किया जाना चाहिए - यकीन है कि संकलक मृत कोड बाहर का अनुकूलन करना चाहिए, लेकिन क्यों कि पर भरोसा करते हैं जब आप अनिवार्य रूप से वास्तविक सी कोड निकाल सकते हैं?

संपादित करें:

नहीं है बल्कि एक बदसूरत है कि आप उपयोग करने में सक्षम हो सकता है मैक्रो तर्क stringification शामिल चाल:

#include <string.h> 
#include <stdio.h> 

#define X 

#define ERROR_(NAME, TEXT) \ 
     if (strcmp("", #NAME) == 0) \ 
       printf("%s\n", TEXT) 
#define ERROR(n, t) ERROR_(n, t) 

int main() { 
    ERROR(X, "Error: X"); 
    ERROR(Y, "Error: Y"); 

    return 0; 
} 

यह आउटपुट:

$ ./test 
Error: X 

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

अस्वीकरण: अपने जोखिम पर इस का प्रयोग करें!

(... क्योंकि मैं सबसे निश्चित रूप से इसका इस्तेमाल नहीं होगा!)

संपादित करें 2:

उपरोक्त कार्यक्रम के लिए gcc -O0 -S के विधानसभा उत्पादन होता है:

 .file "test.c" 
     .section  .rodata 
.LC0: 
     .string "Error: X" 
     .text 
.globl main 
     .type main, @function 
main: 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     movq %rsp, %rbp 
     .cfi_offset 6, -16 
     .cfi_def_cfa_register 6 
     movl $.LC0, %edi 
     call puts 
     movl $0, %eax 
     leave 
     ret 
     .cfi_endproc 
.LFE0: 
     .size main, .-main 
     .ident "GCC: (GNU) 4.4.3" 
     .section  .note.GNU-stack,"",@progbits 

भी अनुकूलन के साथ, जीसीसी इस कार्यक्रम को एक puts() कॉल पर कम कर देता है।इस कार्यक्रम के बिल्कुल वैसा ही विधानसभा उत्पादन का उत्पादन:

#include <stdio.h> 

int main() { 
    puts("Error: X"); 

    return 0; 
} 

इसलिए, आप शायद अपने संकलक और किसी भी अनुकूलन के आधार पर किसी भी प्रदर्शन के मुद्दों के लिए, नहीं जा रहे हैं ...

+0

नहीं, यह अच्छा नहीं है। मैं हमेशा एएसएसईआरटी को परिभाषित करना चाहता हूं, लेकिन यदि NAME अपरिभाषित है, तो मैं कुछ भी नहीं करना चाहता हूं। इसके अलावा, मैं एक #ifdef –

+0

@Miklos Maroti साथ ASSERT के हर उपयोग बंद नहीं करना चाहती: तो नाम की परिभाषा वैश्विक नहीं है, ASSERT है, जबकि, और आप काम करने के लिए केवल जब NAME परिभाषित किया गया है ASSERT करना चाहते हैं? – thkala

+0

मैं इस तरह कोड लिखना चाहता हूं: ASSERT (UART, var> = 0); एसएसएसईआरटी (एसपीआई, var == 0); तो अगर मैं UART परिभाषित, तो सभी UART दावे पर दिया जाना चाहिए, अगर मैं एसपीआई परिभाषित करते हैं, तो सभी SPI दावे चालू होना चाहिए, और मैं उप की एक पूर्वनिर्धारित निश्चित संख्या नहीं करना चाहते, यानी ASSERT_UART, ASSERT_SPI नहीं एक अच्छा समाधान है । –

5

ठीक है, के आधार पर

 
#define DEFINEDX(NAME) ((#NAME)[0] == 0) 
#define DEFINED(NAME) DEFINEDX(NAME) 

यह अगर नाम परिभाषित किया गया है की जाँच करेगा और इसलिए यह अपनी पहली चरित्र पर 0 से रिक्त स्ट्रिंग पर फैलता है, या यह जो cas में अपरिभाषित है: पिछले पोस्ट मैं इस विचार है, जो काम करने के लिए लगता है मिल गया ई यह खाली स्ट्रिंग नहीं है। यह, जीसीसी के साथ काम करता है ताकि एक

 
if(DEFINED(MACRO)) 
    ... 
+0

ध्यान रखें कि यह सी कथन का उपयोग करता है और केवल प्रीकंपलर में पेट्री का विस्तार किया जाएगा। मैं समझता हूँ के रूप में, सी-संकलक तो पता चलता है कि हालत का नतीजा स्थिर है और अप्रयुक्त कोड ... – Johanness

+1

कूल समाप्त, लेकिन यह केवल खाली मैक्रो के लिए काम करता है ... यही कारण है कि अगर आप #define एम वाई करते हैं, तो परिभाषित किया गया है (एम) वापस आ जाएगी 0 (जीसीसी 4.5.1 के साथ परीक्षण) – John

11

comex द्वारा एक मैक्रो 1 करने के लिए विस्तारित किया गया है लिख सकते हैं अगर तर्क 1. अन्यथा यह 0 करने के लिए विस्तारित किया गया है करने के लिए परिभाषित किया गया है:

#define is_set(macro) is_set_(macro) 
#define macrotest_1 , 
#define is_set_(value) is_set__(macrotest_##value) 
#define is_set__(comma) is_set___(comma 1, 0) 
#define is_set___(_, v, ...) v 

आप इसे उपयोग कर सकते हैं इस प्रकार है:

if (is_set(MACRO)) { 
    /* Do something when MACRO is set */ 
} 
+1

यह (अब) जवाब – dashesy

+0

संदर्भित लिंक काम नहीं करता के रूप में स्वीकार किया जाना चाहिए। क्यूशन और उत्तर के साथ सामान्य समस्या यह है कि कम से कम प्रासंगिक भाग का हवाला देते हुए बाहरी लिंक पर भरोसा करते हैं। ध्यान दें कि यह साइट-नियमों और वैध डाउनवोट कारण के खिलाफ है। – Olaf

+1

@ ओलाफ, लिंक मेरे लिए काम करता है। यह जी पर उपयोगकर्ता प्रोफ़ाइल के लिए एक वैध लिंक की तरह दिखता है +: 'https://plus.google.com/u/ {आईडी}/{आईडी}/posts' – gavv

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