2010-07-09 13 views
8

क्या कोई बता सकता है कि g ++ __FUNCTION__ 'मैक्रो' को फ़ंक्शन नाम वाले स्ट्रिंग के साथ बदलता है? ऐसा लगता है कि यह नहीं की जगह ले सकता जब तक यह स्रोत कोड के वाक्य-शुद्धता की जांच की है, यानी निम्नलिखितg ++ __FUNCTION__ समय बदलना

#include <whatsneeded> 
#define DBG_WHEREAMI __FUNCTION__ __FILE__ __LINE__ 

int main(int argc, char* argv) 
{ 
    printf(DBG_WHEREAMI "\n"); //* 
} 
के बाद से

काम नहीं करेगा स्रोत लग रहा है

g++ -E test.cc 

का उपयोग कर preprocessing के बाद

की तरह
[...] 

int main(int argc, char* argv) 
{ 
    printf(__FUNCTION__ "test.cc" "6" "\n"); //* 
} 

और अब संकलक सही ढंग से फेंकता है क्योंकि * एड लाइन गलत है।

क्या स्ट्रिंग के साथ उस प्रतिस्थापन को पहले चरण में मजबूर करने का कोई तरीका है ताकि लाइन सही हो?

__FUNCTION__ वास्तव में एक स्ट्रिंग के साथ बदल दिया गया है? या यह संकलित कोड में एक चर है?

उत्तर

15

वहाँ पहले के किसी चरण ताकि लाइन सही है के लिए एक स्ट्रिंग के साथ कि प्रतिस्थापन के लिए मजबूर करने का कोई तरीका है किया जाना चाहिए?

सं __FUNCTION__ (और इसके मानकीकृत समकक्ष, __func__) संकलक निर्माणों हैं। दूसरी ओर __FILE__ और __LINE__, प्रीप्रोसेसर संरचनाएं हैं। __FUNCTION__ एक प्रीप्रोसेसर निर्माण करने का कोई तरीका नहीं है क्योंकि प्रीप्रोसेसर को सी ++ भाषा का कोई ज्ञान नहीं है। जब एक स्रोत फ़ाइल को प्रीप्रोसेस्ड किया जा रहा है, तो प्रीप्रोसेसर को इस बारे में कोई जानकारी नहीं है कि फ़ंक्शन यह देख रहा है क्योंकि इसमें फ़ंक्शंस की अवधारणा भी नहीं है।

दूसरी ओर, पूर्वप्रक्रमक पता है जो फ़ाइल उस पर काम कर रहा है करता है, और यह भी फ़ाइल इसे देख रहा है की जो लाइन जानता है, तो यह __FILE__ और __LINE__ संभाल करने में सक्षम है।

यही कारण है कि __func__ को स्थिर स्थानीय चर के बराबर परिभाषित किया गया है (यानी कंपाइलर निर्माण); केवल संकलक ही इस कार्यक्षमता प्रदान कर सकते हैं।

3

आप प्रीप्रोसेसर मैक्रो की तरह __FUNCTION__ का उपयोग कर रहे हैं, लेकिन यह एक चर है (कृपया http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html पढ़ें)।

परीक्षण के लिए printf("%s", __FUNCTION__) आज़माएं और यह फ़ंक्शन नाम प्रिंट करेगा।

2

__FUNCTION__ मानक नहीं है। __func__ का प्रयोग करें।

<ret-type> function_name(<args>) 
{ 
    static const char __func__[] = "function-name"; 
    ... 
2

C/C++ में, पूर्वप्रक्रमक "my " "name " "is " "Bob" स्ट्रिंग शाब्दिक "my name is Bob" में बदल जाएगी;: documentation कहते हैं, यह के रूप में अगर है चूंकि __FILE__ और __LINE__ प्रीप्रोसेसर निर्देश हैं, "We are on line " __LINE__ कंपाइलर को "हम लाइन 27 पर" पास करेंगे।

__FUNCTION__ आमतौर पर __func__ के लिए समानार्थी है। __func__ को एक छद्म-फ़ंक्शन के रूप में सोचा जा सकता है जो उस फ़ंक्शन का नाम देता है जिसमें इसे कहा जाता है। यह केवल कंप्रेसर द्वारा किया जा सकता है, न कि प्रीप्रोसेसर द्वारा। क्योंकि __func__ का प्रीप्रोसेसर द्वारा मूल्यांकन नहीं किया जाता है, इसलिए आपको स्वचालित समावेशन नहीं मिलता है। तो अगर आप printf उपयोग कर रहे हैं यह द्वारा printf("the function name is %s", __func__);

1

क्या आप यह चाहते हैं?

#include <stdio.h> 

#define DBG_WHEREAMI(X) printf("%s %s(%d): %s\n",__func__,__FILE__,__LINE__,X) 

int main(int argc, char* argv) 
{ 
    DBG_WHEREAMI("Starting"); 
} 

नोट: जब से तुम सी के रूप में इस चिह्नित ++ आप शायद यकीन है कि यह सुरक्षित टाइप है बनाने के लिए iostreams का उपयोग करना चाहिए।

+0

दुर्भाग्य से, इस तरह 'DBG_WHEREAMI (" त्रुटि कोड% d ", errorCode)' कुछ करने के लिए अनुमति नहीं है। इसे काम करने के लिए नहीं बनाया जा सकता है, या तो (कम से कम पोर्टेबल नहीं) क्योंकि सी ++ में (अभी तक) भिन्नता वाले मैक्रोज़ नहीं हैं। –

+0

काफी नहीं ... मैं सोच रहा था कि क्या मैं संकलन समय पर __func__ युक्त स्ट्रिंग उत्पन्न कर सकता हूं ताकि रनटाइम स्थिर हो। जो असंभव प्रतीत होता है। – bbb

+0

@bbb: यह 'स्थिर स्थिरांक 'है, और इसे रनटाइम पर उत्पन्न होने का शून्य मौका है। –

0
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__); 

हाँ, मुझे पता है कि यह वास्तव में वही नहीं है।

0

ध्यान दें कि यदि आप कक्षा बनाते हैं, तो आप किसी भी प्रकार के संदेश से एक संदेश बना सकते हैं, जिसका अर्थ है कि आप < < ऑपरेटर या प्रिंटफ़ (3 सी) में प्रारूप का समान प्रभाव डालते हैं। कुछ इस तरह:

// make sure log remains copyable 
class log 
{ 
public: 
    log(const char *function, const char *filename, int line) 
    { 
    f_message << function << ":" << filename << ":" << line << ": "; 
    } 
    ~log() 
    { 
    //printf("%s\n", f_message.str().c_str()); -- printf?! 
    std::cerr << f_message.str() << std::endl; 
    } 

    log& operator() (const char *value) 
    { 
    f_message << value; 
    } 
    log& operator() (int value) 
    { 
    f_message << value; 
    } 
    // repeat with all the types you want to support in the base class 
    // (should be all the basic types at least) 
private: 
    sstream f_message; 
}; 

// start the magic here 
log log_error(const char *func, const char *file, int line) 
{ 
    log l(func, file, line); 
    return l; 
} 

// NOTE: No ';' at the end here! 
#define LOG_DEBUG log_error(__func__, __FILE__, __LINE__) 

// usage sample: 
LOG_DEBUG("found ")(count)(" items"); 

ध्यान दें कि आप() के बजाय < < ऑपरेटरों की घोषणा कर सकता है।

LOG_DEBUG << "found " << count << " items"; 

निर्भर करता है जो आप का उपयोग करना पसंद: उस मामले में परिणामी उपयोग कुछ इस तरह होगा। मुझे पसंद है() क्योंकि यह आपके अभिव्यक्तियों को स्वचालित रूप से सुरक्षित करता है। अर्थात अगर आप उत्पादन करना चाहते हैं "गिनती < < 3" तो तुम लिखने के लिए होगा:

LOG_DEBUG << "found " << (count << 3) << " items"; 
संबंधित मुद्दे