2014-10-30 5 views
13

मुझे लिंक से संबंधित चीजों को छोड़कर मानक में कोई टिप्पणी नहीं दिखाई देती है।'बाहरी "सी" `फ़ंक्शन के प्रकार का एक हिस्सा है?

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

#include <type_traits> 

extern "C" { 
    int c_func(int); 
} 

int cpp_func(int); 

static_assert(!std::is_same<decltype(c_func), decltype(cpp_func)>::value, 
       "It should not be the same type"); 

static_assert विफल रहता है के बाद से जीसीसी समझता है उन कार्यों में एक ही प्रकार की है।

  • extern "C" फ़ंक्शन के प्रकार का एक हिस्सा है?
  • मैं कैसे जांचूं कि कोई फ़ंक्शन सी कॉलिंग कन्वेंशन या सी ++ कॉलिंग कन्वेंशन का उपयोग करता है या नहीं?
+0

सी ++ समर्थन करता है उदा। समारोह अधिभार। विभिन्न तर्क प्रकारों के साथ दो कार्य, लेकिन एक ही नाम - यह सी लिंकिंग के साथ नहीं किया जा सकता है क्योंकि अद्वितीय नाम रखने के लिए फ़ंक्शन नाम को उलझाया जाना चाहिए। – keltar

+0

@ केल्टार हां, आप सही हैं, और यही वह नहीं है जो मैं यहां पूछ रहा हूं। यह कॉलिंग सम्मेलन के बारे में है, नाम उलझन में नहीं है। प्रत्येक दस्तावेज़, क्यू/ए 'बाहरी' सी '' के बारे में इंटरनेट पर पाया गया है, नाम के बारे में बताता है लेकिन कॉलिंग सम्मेलन नहीं। – kukyakya

+1

चूंकि इसका उपयोग विधियों पर नहीं किया जा सकता है (और इसलिए इस स्केल को प्रभावित नहीं कर सकता है) - हाँ, इसे केवल कन्वर्टिंग को संशोधित किए बिना मैंगलिंग को अक्षम करना चाहिए, जब तक कि स्पष्ट रूप से अन्यथा निर्दिष्ट न हो (उदा। '__attribute__' कंपाइलर-विशिष्ट कमांड के साथ)। आप तुलना करने वाले दोनों प्रकार 'int (*) (int) 'हैं। – keltar

उत्तर

16

मानक यह स्पष्ट करता है कि भाषा लिंकेज वास्तव में एक समारोह प्रकार खुद की संपत्ति है:

सभी समारोह प्रकारों, बाहरी लिंकेज के साथ समारोह के नाम, और चर नाम बाहरी लिंकेज के साथ भाषा संबंध है।

मामले कि पर्याप्त स्पष्ट नहीं था, वहाँ एक नोट (जोर मेरा) कि अभीष्ट अर्थ स्पष्ट बनाता है:

[नोट: क्योंकि भाषा लिंकेज एक का हिस्सा है फंक्शन प्रकार, जब सी फ़ंक्शन पर पॉइंटर के माध्यम से अप्रत्यक्ष हो रहा है, तो जिस फ़ंक्शन को परिणामस्वरूप लवल्यू संदर्भित करता है उसे सी फ़ंक्शन माना जाता है। - अंत टिप्पणी]

इसके अलावा, अलग भाषा के साथ

दो समारोह प्रकार लिंकेज भिन्न प्रकार भले ही वे अन्यथा समान हैं कर रहे हैं।

तो अपने पहले सवाल का जवाब है:

  • हाँ, extern "C" एक समारोह के प्रकार का हिस्सा है।

हालांकि, अधिकांश कंपाइलर सी और सी ++ भाषा संबंध के साथ कार्यों के प्रकारों के बीच अंतर करने में विफल रहते हैं। यह उदाहरण के लिए जीसीसी (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316) में एक लंबे समय से चलने वाली बग है; डुप्लिकेट की सूची देखें)। मैंने पूरे धागे को ध्यान से नहीं पढ़ा, लेकिन ऐसा लगता है कि जीसीसी ने नियम लागू करने के लिए बहुत सारे मौजूदा कोड तोड़ दिए होंगे कि वे वास्तव में अलग-अलग प्रकार हैं। यह संभवतः यह भी है कि क्यों अन्य कंपाइलर मानक के अनुरूप होने में विफल रहते हैं।

यह देखते हुए कि, अपने दूसरे सवाल का जवाब होने लगते हैं:

  • शायद संकलन समय पर इस जाँच करने के लिए कोई पोर्टेबल तरीका नहीं है। निश्चित रूप से अनुवाद के बाद आप हमेशा अंदर जा सकते हैं और ऑब्जेक्ट फ़ाइल देख सकते हैं और देख सकते हैं कि नाम उलझन में है या नहीं।

लेकिन सिद्धांत में, अपने स्थिर अभिकथन तरह से आपको लगता है यह होना चाहिए काम करने के लिए माना जाता है। यह अभ्यास में मामला नहीं है।

परिशिष्ट:

तो मानक की मेरी समझ सही है, तो उदाहरण के लिए समारोह टेम्पलेट निम्नलिखित

template <typename R, typename... A> 
void f(R(*)(A...)); 

एक समारोह है कि एक समारोह के लिए सूचक को स्वीकार करेंगे निर्माण करने के लिए instantiated नहीं किया जा सकता सी भाषा लिंकेज के साथ तर्क के रूप में, R(*)(A...) टाइप करें "सी ++ भाषा लिंकेज के साथ के तर्क लेने औरपर तर्क लेने के साथ फ़ंक्शन करने के लिए सूचक है"।

यदि कंपाइलर्स वास्तव में इस तरह काम करते हैं, तो यह देखना आसान है कि आप सामान्य रूप से यह निर्धारित कर सकते हैं कि किसी फ़ंक्शन में सी या सी ++ भाषा संबंध है या नहीं।

लेकिन इस उदाहरण को यह भी स्पष्ट करना चाहिए कि यदि संकलक वास्तव में इस तरह से काम करते हैं तो मौजूदा कोड कितना बुरी तरह टूट जाएगा।

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