2012-01-08 15 views
31

सी ++ में, मैं कुछ परिस्थितियों में पैरामीटर का नाम छोड़ देता हूं। लेकिन सी में, जब मुझे पैरामीटर का नाम छोड़ दिया गया तो मुझे एक त्रुटि मिली।पैरामीटर नाम छोड़ा गया, सी ++ बनाम सी

void foo(int); //forward-decl, it's OK to omit the parameter's name, in both C++ and C 

int main() 
{ 
    foo(0); 
    return 0; 
} 

void foo(int) //definition in C, it cannot compile with gcc 
{ 
    printf("in foo\n"); 
} 

void foo(int) //definition in C++, it can compile with g++ 
{ 
    cout << "in foo" << endl; 
} 

कि क्यों है:

यहाँ कोड है? क्या मैं सी फ़ंक्शन परिभाषा में पैरामीटर का नाम नहीं छोड़ सकता?

+2

बहु भाषा स्रोत फ़ाइलों लेखन (बहुत) कड़ी मेहनत है। मेरा सुझाव है कि आप प्रत्येक एकल स्रोत फ़ाइल को केवल एक भाषा में रखें। – pmg

+0

@pmg, आपकी सलाह के लिए धन्यवाद,: – Alcott

+0

लेकिन यदि आप सी और सी ++ दोनों में संकलित करना चाहते हैं, तो 'printf' और' str :: cout' का उपयोग करने के लिए अलग-अलग फ़ंक्शंस लिखने की आवश्यकता नहीं है। 'printf' दोनों भाषाओं के लिए काम करता है। मैं दो कार्यों का उपयोग करने के खिलाफ पुनर्मूल्यांकन करूंगा जिसे एक के रूप में लिखा जा सकता है, क्योंकि उनकी कार्यक्षमता समान नहीं हो सकती है। –

उत्तर

33

नहीं, सी में, आप फ़ंक्शन परिभाषाओं में पैरामीटर के लिए पहचानकर्ताओं को छोड़ नहीं सकते हैं।

C99 मानक का कहना है:

[6.9.1.5] declarator एक पैरामीटर प्रकार सूची में शामिल हैं, तो प्रत्येक पैरामीटर के घोषणा में पहचान करने की एक पैरामीटर सूची के विशेष मामले के अलावा शामिल होगा टाइप शून्य के एक पैरामीटर से युक्त, जिसमें इस मामले में कोई पहचानकर्ता नहीं होगा। नहीं घोषणा सूची का पालन करेंगे।

सी ++ 14 मानक का कहना है:

[8.3.5.11] एक पहचानकर्ता वैकल्पिक रूप से एक पैरामीटर नाम के रूप में प्रदान किया जा सकता; यदि फ़ंक्शन परिभाषा में मौजूद है, तो यह पैरामीटर (कभी-कभी "औपचारिक तर्क" कहा जाता है) का नाम देता है। [नोट: विशेष रूप से, पैरामीटर नाम भी समारोह में वैकल्पिक हैं परिभाषाएँ और विभिन्न घोषणाओं में एक पैरामीटर और एक समारोह की परिभाषा के लिए उपयोग होने वाले नाम एक ही होने की जरूरत नहीं।]

+0

तो, एक चर नाम को पहचानकर्ता कहा जाता है? –

+5

@ श्री टैमर: सभी परिवर्तनीय नाम पहचानकर्ता हैं, लेकिन कुछ पहचानकर्ता परिवर्तनीय नाम नहीं हैं। –

+0

@DietrichEpp: मुझे लगता है, धन्यवाद :)। एक त्वरित खोज के साथ मैंने पाया [यह] (http://msdn.microsoft.com/en-us/library/565w213d.aspx)। –

4

आप फ़ंक्शन प्रोटोटाइप में पैरामीटर नाम को छोड़ सकते हैं, लेकिन आपको इसे फ़ंक्शन कार्यान्वयन में घोषित करना होगा। उदाहरण के लिए, इस संकलित करता है तथा जीसीसी 4.6.1

void foo(int, int); 

void foo(int value, int secondValue) 
{ 
    printf("In foo with value %d and %d!\n", value, secondValue); 
} 

int main(int argc, char **argv) 
{ 
    foo(10, 15); 
    return 0; 
} 

आउटपुट के तहत ठीक चलाता है: In foo with value 10 and 15!

के रूप में क्यों (क्योंकि मानकों के अलावा अन्य ऐसा कहते): सी ++ आप का उपयोग किए बिना एक समारोह कॉल करने के लिए अनुमति देता है सभी तर्क, जबकि सी नहीं करता है। यदि आप सी में किसी फ़ंक्शन में सभी तर्कों की आपूर्ति नहीं करते हैं, तो संकलक error: too few arguments to function 'foo'

+4

सी ++ * आपको कॉल में तर्कों को छोड़ने की अनुमति नहीं देता है जब तक कि संबंधित पैरामीटर में डिफ़ॉल्ट मान न हों। और उस स्थिति में, डिफ़ॉल्ट मान पूरी तरह से पारित किए जाते हैं, और फ़ंक्शन को तर्कों के लिए नाम प्रदान करना पड़ता है यदि यह उनके मूल्यों का संदर्भ दे रहा है। अंतर यह है कि सी ++ में और अधिक मामले हैं जहां एक फ़ंक्शन के लिए इसके किसी पैरामीटर को अनदेखा करना समझ में आता है। –

15

कारण यह है कि है यही संबंधित भाषा मानकों का कहना है, लेकिन अंतर के लिए एक तर्क है।

यदि आप पैरामीटर के लिए नाम प्रदान नहीं करते हैं, तो फ़ंक्शन उस पैरामीटर को संदर्भित नहीं कर सकता है।

सी में, यदि कोई फ़ंक्शन इसके पैरामीटर को अनदेखा करता है, तो आमतौर पर यह घोषणा और परिभाषा से इसे हटाने के लिए समझ में आता है, और किसी भी कॉल में इसे पास नहीं करता है। एक अपवाद एक कॉलबैक फ़ंक्शन हो सकता है, जहां कार्यों का संग्रह सभी एक ही प्रकार का होना चाहिए, लेकिन उनमें से सभी आवश्यक रूप से अपने पैरामीटर का उपयोग नहीं करते हैं। लेकिन यह एक बहुत ही आम परिदृश्य नहीं है।

सी ++ में, यदि फ़ंक्शन कुछ अभिभावक वर्ग में परिभाषित फ़ंक्शन से लिया गया है, तो उसके पास पैरेंट मानों में से किसी एक के लिए कोई उपयोग नहीं होने पर भी माता-पिता के समान हस्ताक्षर होना चाहिए।

(ध्यान दें कि यह डिफ़ॉल्ट पैरामीटर से संबंधित नहीं है; यदि सी ++ में पैरामीटर का डिफ़ॉल्ट मान है, तो कॉलर को इसे स्पष्ट रूप से पास नहीं करना पड़ता है, लेकिन फ़ंक्शन परिभाषा को अभी भी एक नाम प्रदान करना होगा यदि यह जा रहा है इसका संदर्भ लें।)

5

पूरी तरह से व्यावहारिक स्तर पर, मैंने इस दैनिक से निपट लिया है। तिथि का सबसे अच्छा समाधान प्री-प्रोसेसर का उपयोग करना है। मेरे आम हेडर फाइल में शामिल हैं:

//------------------------------------------------------------------------- 
// Suppress nuisance compiler warnings. Yes, each compiler can already 
// do this, each differently! VC9 has its UNREFERENCED_PARAMETER(), 
// which is almost the same as the SUPPRESS_UNUSED_WARNING() below. 
// 
// We append _UNUSED to the variable name, because the dumb gcc compiler 
// doesn't bother to tell you if you erroneously _use_ something flagged 
// with __attribute__((unused)). So we are forced to *mangle* the name. 
//------------------------------------------------------------------------- 
#if defined(__cplusplus) 
#define UNUSED(x)  // = nothing 
#elif defined(__GNUC__) 
#define UNUSED(x)  x##_UNUSED __attribute__((unused)) 
#else 
#define UNUSED(x)  x##_UNUSED 
#endif 

अप्रयुक्त के उपयोग का एक उदाहरण है:

void foo(int UNUSED(bar)) {} 

कभी-कभी आप वास्तव में एक ज़ोर() या डिबग बयान में उदाहरण के लिए, पैरामीटर का उल्लेख करने की जरूरत है। आप ऐसा कर सकते हैं के माध्यम से:

#define USED_UNUSED(x) x##_UNUSED // for assert(), debug, etc 

इसके अलावा, निम्नलिखित उपयोगी होते हैं:

#define UNUSED_FUNCTION(x) inline static x##_UNUSED // "inline" for GCC warning 
#define SUPPRESS_UNUSED_WARNING(x) (void)(x) // cf. MSVC UNREFERENCED_PARAMETER 

उदाहरण:

UNUSED_FUNCTION(int myFunction)(int myArg) { ...etc... } 

और:

void foo(int bar) { 
#ifdef XXX 
    // ... (some code using bar) 
#else 
    SUPPRESS_UNUSED_WARNING(bar); 
#endif 
} 
+1

यह दो दिन देर हो चुकी है। मुझे आशा है कि यह * अप्रयुक्त * पूर्ण नहीं है। –

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