C फ़ंक्शंस का नाम क्यों नहीं रखा जा सकता?


136

मेरे पास हाल ही में एक साक्षात्कार था और एक प्रश्न पूछा गया कि extern "C"C ++ कोड का उपयोग क्या है । मैंने उत्तर दिया कि यह C ++ कोड में C फ़ंक्शन का उपयोग करना है क्योंकि C नाम-मैनलिंग का उपयोग नहीं करता है। मुझसे पूछा गया कि C नाम-प्रबंधन का उपयोग क्यों नहीं करता है और ईमानदार होने के लिए मैं जवाब नहीं दे सकता।

मैं समझता हूं कि जब C ++ कंपाइलर फ़ंक्शंस संकलित करता है, तो यह मुख्य रूप से फ़ंक्शन को एक विशेष नाम देता है क्योंकि हम C ++ में एक ही नाम के अतिभारित कार्य कर सकते हैं, जिसे संकलित समय पर हल किया जाना चाहिए। C में, फ़ंक्शन का नाम वही रहेगा, या हो सकता है कि उसके पहले एक _ हो।

मेरी क्वेरी है: C ++ कंपाइलर को C फ़ंक्शन भी करने की अनुमति देने में क्या गलत है? मुझे लगता है कि यह कोई फर्क नहीं पड़ता कि संकलक उन्हें क्या नाम देता है। हम C और C ++ में इसी तरह से कार्य करते हैं।


75
C को नामों को जोड़ने की आवश्यकता नहीं है , क्योंकि इसमें फ़ंक्शन ओवरलोडिंग नहीं है।
EOF

9
यदि आप C ++ कंपाइलर के साथ C लाइब्रेरीज़ को लिंक करते हैं तो C ++ कंपाइलर फ़ंक्शन के नाम को कैसे बताता है?
Mat

6
"मैंने उत्तर दिया कि यह C ++ कोड में C फ़ंक्शन का उपयोग करना है क्योंकि C नाम-मैनलिंग का उपयोग नहीं करता है।" - मुझे लगता है कि यह दूसरा तरीका है। बाहरी "C" एक C कंपाइलर में C ++ फ़ंक्शन को प्रयोग करने योग्य बनाता है। source
रोज़ीना

3
@ Engineer999: और अगर आप C का सबसेट संकलित करते हैं, जो C ++ कंपाइलर के साथ C ++ भी है, तो फ़ंक्शन नाम वास्तव में मैंगल्ड हो जाएंगे। लेकिन अगर आप अलग-अलग संकलक के साथ बनाई गई बायनेरिज़ को लिंक करने में सक्षम होना चाहते हैं, तो आप नाम के नामकरण नहीं चाहते हैं।
EOF

13
C नाम करता है । आमतौर पर मैंगल्ड नाम एक अंडरस्कोर से पहले होने वाले फ़ंक्शन का नाम है। कभी-कभी यह एक अंडरस्कोर के बाद फ़ंक्शन का नाम है। extern "C"इस तरह से नाम जोड़ने के लिए कहते हैं कि "" सी संकलक होगा।
पीट बेकर

जवाबों:


187

यह ऊपर वर्णित उत्तर की तरह था, लेकिन मैं चीजों को संदर्भ में रखने की कोशिश करूंगा।

सबसे पहले, सी पहले आया था। जैसे, C क्या करता है, की तरह, "डिफ़ॉल्ट"। यह नाम नहीं मांगता है क्योंकि यह सिर्फ नहीं है। एक फ़ंक्शन नाम एक फ़ंक्शन नाम है। एक वैश्विक एक वैश्विक है, और इसी तरह।

फिर C ++ साथ आया। C ++ सी के समान लिंकर का उपयोग करने में सक्षम होना चाहता था, और सी में लिखे कोड के साथ लिंक करने में सक्षम होना चाहता था। लेकिन C ++ C को "मैनरिंग" (या, वहां की कमी) के रूप में नहीं छोड़ सकता है। निम्नलिखित उदाहरण देखें:

int function(int a);
int function();

C ++ में, ये अलग-अलग निकायों के साथ, अलग-अलग कार्य हैं। यदि उनमें से कोई भी मंगली नहीं है, तो दोनों को "फ़ंक्शन" (या "_function") कहा जाएगा, और लिंकर एक प्रतीक के पुन: निर्धारण के बारे में शिकायत करेगा। C ++ समाधान तर्क प्रकारों को फ़ंक्शन नाम में जकड़ना था। तो, एक को बुलाया जाता है _function_intऔर दूसरे को बुलाया जाता है _function_void(वास्तविक प्रबंधन योजना नहीं) और टकराव से बचा जाता है।

अब हम एक समस्या से बचे हैं। यदि int function(int a)एक C मॉड्यूल में परिभाषित किया गया था, और हम केवल C ++ कोड में उसके हेडर (यानी घोषणा) ले रहे हैं और इसका उपयोग करते हुए, कंपाइलर लिंकर को आयात करने के लिए एक निर्देश उत्पन्न करेगा _function_int। जब फ़ंक्शन को C मॉड्यूल में परिभाषित किया गया था, तो उसे कहा नहीं गया था। इसे बुलाया गया था _function। यह एक लिंकर त्रुटि का कारण होगा।

उस त्रुटि से बचने के लिए, फ़ंक्शन की घोषणा के दौरान , हम कंपाइलर को बताते हैं कि यह एक ऐसा फ़ंक्शन है जिसे सी कंपाइलर के साथ जोड़ा या संकलित किया गया है:

extern "C" int function(int a);

C ++ कंपाइलर अब आयात करने के _functionबजाय जानता है _function_int, और सब ठीक है।


1
@ शशमेश: मैंने यह कहीं और पूछा है, लेकिन, C ++ के संकलित पुस्तकालयों में जोड़ने के बारे में क्या? जब संकलक मेरे कोड को एक C ++ संकलित पुस्तकालय में फ़ंक्शन में से एक के माध्यम से आगे बढ़ रहा है और संकलित कर रहा है, तो यह कैसे पता चलता है कि फ़ंक्शन को केवल उसकी घोषणा या फ़ंक्शन कॉल को देखने या देने के लिए किस नाम को दिया जाए? यह कैसे पता चलेगा कि इसे कहाँ परिभाषित किया गया है, यह नाम के साथ-साथ कुछ और है? तो C ++ में एक मानक नाम-प्रबंध विधि होनी चाहिए?
अभियंता

2
हर कंपाइलर इसे अपने खास तरीके से करता है। यदि आप एक ही संकलक के साथ सब कुछ संकलित कर रहे हैं तो इससे कोई फर्क नहीं पड़ता। लेकिन अगर आप उपयोग करने का प्रयास करते हैं, तो कहें, एक पुस्तकालय जो बोरलैंड के संकलक के साथ संकलित किया गया था, एक प्रोग्राम से जो आप माइक्रोसॉफ्ट के संकलक के साथ बना रहे हैं, अच्छी तरह से ... सौभाग्य; आपको इसकी आवश्यकता होगी :)
VY

6
@ Engineer999 कभी सोचा है कि पोर्टेबल सी ++ लाइब्रेरी जैसी कोई चीज क्यों नहीं है, लेकिन वे या तो कंपाइलर (और मानक लाइब्रेरी) के बिल्कुल संस्करण (और झंडे) का उपयोग करते हैं जो आपको सी एपीआई का उपयोग करना या बस निर्यात करना है? तुम वहाँ जाओ। C ++ अब तक की सबसे कम पोर्टेबल भाषा का आविष्कार किया है, जबकि C इसके ठीक विपरीत है। उस संबंध में प्रयास हैं, लेकिन अभी के लिए यदि आप कुछ ऐसा चाहते हैं जो वास्तव में पोर्टेबल हो, तो आप सी के साथ चिपके रहेंगे
वू

1
@ अच्छा, सिद्धांत रूप में, आपको मानक जैसे का पालन करके पोर्टेबल कोड लिखने में सक्षम होना चाहिए -std=c++11, और मानक के बाहर किसी भी चीज़ के उपयोग से बचें। यह जावा संस्करण घोषित करने के समान है (हालांकि नए जावा संस्करण पिछड़े संगत हैं)। यह मानक दोष नहीं है जो लोग संकलक विशिष्ट एक्सटेंशन और प्लेटफ़ॉर्म आश्रित कोड का उपयोग करते हैं। दूसरी ओर, आप उन्हें दोष नहीं दे सकते हैं, क्योंकि मानक में बहुत सारी चीजें (एस्प IO, सॉकेट्स) गायब हैं। समिति धीरे-धीरे पकड़ में आती दिख रही है। अगर मैं कुछ चूक गया तो मुझे सुधारो।
23

14
@ म्यूको: आप स्रोत पोर्टेबिलिटी / अनुकूलता के बारे में बात कर रहे हैं। यानी एपीआई। वू फिर से संकलन के बिना, द्विआधारी संगतता के बारे में बात कर रहा है । इसके लिए ABI संगतता की आवश्यकता होती है । C ++ कंपाइलर नियमित रूप से संस्करणों के बीच अपने ABI को बदलते हैं। (उदाहरण g ++ भी एक स्थिर ABI की कोशिश नहीं करता है। मेरा मानना ​​है कि वे ABI को केवल मनोरंजन के लिए नहीं तोड़ते हैं, लेकिन वे उन परिवर्तनों से नहीं बचते हैं जिनमें ABI परिवर्तन की आवश्यकता होती है जब कुछ प्राप्त करना होता है और कोई अन्य अच्छा तरीका नहीं होता है इसे करने के लिए।)।
पीटर कॉर्ड्स

45

ऐसा नहीं है कि वे "नहीं" कर सकते हैं, वे सामान्य रूप से नहीं हैं

यदि आप C नामक किसी लाइब्रेरी में कोई फ़ंक्शन कॉल करना चाहते हैं foo(int x, const char *y), तो यह आपके C ++ कंपाइलर को उस foo_I_cCP()(या जो कुछ भी, बस यहाँ पर मौके पर एक mangling स्कीम बना देता है) को केवल इसलिए अच्छा नहीं होने देता है।

वह नाम हल नहीं करेगा, फ़ंक्शन C में है और उसका नाम उसके तर्क प्रकारों की सूची पर निर्भर नहीं करता है। तो C ++ कंपाइलर को यह जानना होगा, और उस कार्य को चिह्नित करना होगा, जिससे मैनिंग करने से बचने के लिए C हो।

याद रखें कि सी फ़ंक्शन एक पुस्तकालय में हो सकता है जिसका स्रोत कोड आपके पास नहीं है, आपके पास सभी पूर्व-संकलित बाइनरी और हेडर है। तो आपका C ++ कंपाइलर "यह अपनी बात है" नहीं कर सकता, यह नहीं बदल सकता है कि लाइब्रेरी में आखिर क्या है।


यह वह हिस्सा है जो मुझे याद आ रहा है। C ++ कंपाइलर किसी फ़ंक्शन नाम को क्यों रखेगा जब वह इसकी घोषणा देखता है या उसे कॉल करता है। जब यह उनके कार्यान्वयन को देखता है तो क्या यह केवल नाम के नाम को ही नहीं करता है? यह मेरे लिए और अधिक समझ में आता है
Engineer999

13
@ Engineer999: परिभाषा के लिए आपका एक नाम और घोषणा के लिए दूसरा कैसे हो सकता है? "ब्रायन नामक एक फ़ंक्शन है जिसे आप कॉल कर सकते हैं।" "ठीक है मैं ब्रायन को बुलाऊंगा।" "क्षमा करें, ब्रायन नामक कोई फ़ंक्शन नहीं है।" यह ग्राहम कहलाता है।
ऑर्बिट

C ++ संकलित पुस्तकालयों में जोड़ने के बारे में क्या? जब कंपाइलर हमारे कोड के माध्यम से कदम बढ़ा रहा है और संकलित कर रहा है, जो C ++ संकलित पुस्तकालय में किसी एक कार्य को कॉल करता है, तो यह कैसे पता चलता है कि किस फ़ंक्शन को केवल उसकी घोषणा या फ़ंक्शन कॉल को देखने के लिए फ़ंक्शन करना या देना है?
Engineer999

1
@ Engineer999 दोनों को एक ही मेनिंग पर सहमत होना चाहिए। तो वे हेडर फ़ाइल देखते हैं (याद रखें, देशी DLL में बहुत कम मेटाडेटा है - हेडर वह मेटाडेटा हैं), और "आह, ठीक है, ब्रायन वास्तव में ग्राहम होना चाहिए"। यदि यह काम नहीं करता है (जैसे दो असंगत प्रबंध योजनाओं के साथ), तो आपको एक सही लिंक नहीं मिलेगा और आपका आवेदन विफल होने वाला है। C ++ में इस तरह की बहुत सी असंगतताएँ हैं। व्यवहार में, आपको फिर स्पष्ट रूप से मांगे गए नाम का उपयोग करना होगा और अपनी तरफ से मैनबलिंग को अक्षम करना होगा (जैसे कि आप ग्राहम को निष्पादित करने के लिए अपना कोड बताते हैं, ब्रायन को नहीं)। में वास्तविक अभ्यास ... extern "C":)
Luaan

1
@ Engineer999 मैं गलत हो सकता है, लेकिन क्या आपके पास विजुअल बेसिक, C # या जावा (या एक हद तक पास्कल / डेल्फी) जैसी भाषाओं के साथ अनुभव है? इंटरोप बनाने वाले बेहद साधारण लगते हैं। C और विशेष रूप से C ++ में, यह कुछ भी है लेकिन आपके द्वारा सम्मानित करने के लिए बहुत सारे कॉलिंग कन्वेंशन हैं, आपको यह जानना होगा कि किस मेमोरी के लिए कौन जिम्मेदार है, और आपके पास हेडर फाइलें होनी चाहिए जो आपको फ़ंक्शन की घोषणाएं बताती हैं, क्योंकि DLL में स्वयं पर्याप्त जानकारी नहीं होती है - विशेषकर के मामले में शुद्ध C. यदि आपके पास कोई हेडर फ़ाइल नहीं है, तो आपको इसका उपयोग करने के लिए आम तौर पर DLL को अपघटित करना होगा।
लूवन

32

C फ़ंक्शन को C करने के लिए C ++ कंपाइलर की अनुमति देने में क्या गलत है?

वे C फ़ंक्शन किसी भी अधिक नहीं होंगे।

एक फ़ंक्शन केवल एक हस्ताक्षर और एक परिभाषा नहीं है; कैसे एक समारोह में काम करता है बड़े पैमाने पर कॉलिंग सम्मेलन जैसे कारकों से निर्धारित होता है। आपके प्लेटफॉर्म पर उपयोग के लिए निर्दिष्ट "एप्लिकेशन बाइनरी इंटरफ़ेस" बताता है कि सिस्टम एक दूसरे से कैसे बात करते हैं। आपके सिस्टम द्वारा उपयोग में C ++ ABI एक नाम प्रबंधन योजना को निर्दिष्ट करता है, ताकि उस प्रणाली के प्रोग्राम पुस्तकालयों और इसके बाद के कार्यों को कैसे करें, यह जानते हैं। (एक महान उदाहरण के लिए सी ++ इटेनियम एबी पढ़ें। आप बहुत जल्दी देखेंगे कि यह क्यों आवश्यक है।)

आपके सिस्टम पर C ABI के लिए भी यही लागू होता है। कुछ C ABI में वास्तव में एक नाम प्रबंधन योजना (जैसे Visual Studio) होती है, इसलिए यह "नाम प्रबंधन को बंद करना" के बारे में कम और कुछ कार्यों के लिए C ++ ABI से C ABI में स्विच करने के बारे में अधिक है। हम C फ़ंक्शन को C फ़ंक्शन के रूप में चिह्नित करते हैं, जिससे C ABI (C ++ ABI के बजाय) प्रासंगिक है। घोषणा की परिभाषा से मेल खाना चाहिए (उसी परियोजना में या किसी तीसरे पक्ष के पुस्तकालय में), अन्यथा घोषणा व्यर्थ है। इसके बिना, आपके सिस्टम को यह नहीं पता होगा कि उन कार्यों का पता लगाना / इनवॉइस कैसे करना है।

प्लेटफ़ॉर्म C और C ++ ABI को समान क्यों नहीं परिभाषित करता है और इस "समस्या" से छुटकारा पाने के लिए, यह आंशिक रूप से ऐतिहासिक है - मूल C ABI C ++ के लिए पर्याप्त नहीं थे, जिसमें नेमस्पेस, क्लासेस और ऑपरेटर ओवरलोडिंग हैं, सभी जिनमें से किसी को कंप्यूटर के अनुकूल तरीके से किसी प्रतीक के नाम का प्रतिनिधित्व करने की आवश्यकता है - लेकिन कोई यह भी तर्क दे सकता है कि अब C ++ द्वारा C कार्यक्रमों का पालन करना C समुदाय पर अनुचित है, जिसे सामूहिक रूप से और अधिक जटिल बनाना होगा एबीआई सिर्फ कुछ अन्य लोगों की खातिर, जो इंटरऑपरेबिलिटी चाहते हैं।


2
+int(PI/3), लेकिन नमक के एक दाने के साथ: मैं "C ++ ABI" बोलने के लिए बहुत सतर्क रहूंगा ... AFAIK, C ++ ABIs को परिभाषित करने के प्रयास हैं , लेकिन कोई वास्तविक de वास्तविक / de jure मानक नहीं है - isocppin.org - फ़ाइल्स के रूप में /papers/n4028.pdf स्टेट्स (और मैं तहे दिल से सहमत हूं), उद्धरण, यह गहराई से विडंबना है कि वास्तव में C ++ ने हमेशा एक स्थिर द्विआधारी ABI के साथ एपीआई को प्रकाशित करने के तरीके का समर्थन किया है - बाह्य के माध्यम से C ++ के C सबसेट का सहारा लेकर "। C++ Itanium ABIबस इतना ही है - Itanium के लिए कुछ C ++ ABI ... जैसा कि stackoverflow.com/questions/7492180/c-abi-issues-list

3
@vaxquis: हाँ, "C ++ की ABI" नहीं, बल्कि "C ++ ABI" उसी तरह से है जैसे मेरे पास "घर की" है जो हर घर पर काम नहीं करती है। लगता यह स्पष्ट हो सकता है, हालांकि मैं वाक्यांश के साथ बंद शुरू करने से संभव के रूप में स्पष्ट रूप में यह करने की कोशिश की "सी ++ ABI आपके सिस्टम द्वारा उपयोग में " । मैंने स्पष्टता को बाद में संक्षिप्तता के लिए छोड़ दिया, लेकिन मैं एक ऐसा संपादन स्वीकार करूंगा जो भ्रम को कम करता है!
ऑर्बिट

1
एआईयूआई सी अबी का रुझान एक मंच की संपत्ति है, जबकि सी ++ एबीआई एक व्यक्तिगत कंपाइलर की संपत्ति है और अक्सर एक कंपाइलर के व्यक्तिगत संस्करण की संपत्ति भी है। इसलिए यदि आप विभिन्न विक्रेताओं उपकरणों के साथ निर्मित मॉड्यूल के बीच लिंक करना चाहते हैं, तो आपको इंटरफ़ेस के लिए सी एबीआई का उपयोग करना होगा।
प्लगव्यू

बयान "नाम-मांगे गए कार्य सी फ़ंक्शन नहीं होंगे किसी भी अधिक" अतिरंजित नहीं है - अगर नाम से जाना जाता है तो सादे वेनिला सी से नाम-मंगल कार्यों को कॉल करना पूरी तरह से संभव है। यह नाम परिवर्तन सी ABI के लिए इसका कोई कम पालन नहीं करता है, अर्थात यह किसी भी कम C फ़ंक्शन नहीं करता है। दूसरे तरीके से राउंड अधिक समझ में आता है - C ++ कोड "C" घोषित किए बिना C फ़ंक्शन को कॉल नहीं कर सकता है क्योंकि यह कैली के खिलाफ लिंक करने का प्रयास करते समय
पीटर -

@ पीटरए. श्नाइडर: हाँ, शीर्षक वाक्यांश अतिरंजित है। उत्तर के पूरे बाकी हिस्से में प्रासंगिक तथ्यात्मक विवरण है।
ऑर्बिट

21

MSVC वास्तव में C नाम को कम करता है, हालाँकि एक साधारण तरीके से। यह कभी-कभी अपील करता है @4या कोई अन्य छोटी संख्या। यह कॉलिंग कन्वेंशन और स्टैक क्लीनअप की आवश्यकता से संबंधित है।

तो आधार सिर्फ दोषपूर्ण है।


2
यह वास्तव में नाम नहीं है। यह बस एक विक्रेता विशिष्ट नामकरण (या नाम adorning) सम्मेलन है, जो विभिन्न कॉलिंग सम्मेलनों वाले फ़ंक्शन के साथ निर्मित DLL से जुड़े मुद्दों को रोकने के लिए है।
पीटर

2
क्या एक के साथ प्रस्तुत करने के बारे में _?
ऑरेंजडॉग

12
@Peter: वास्तव में एक ही बात है।
ऑर्बिट

5
@ फ्रेंकी_सी: "कॉलर स्टैक को साफ करता है" किसी भी सी मानक द्वारा निर्दिष्ट नहीं है: न तो कॉलिंग कन्वेंशन भाषा के दृष्टिकोण से अन्य की तुलना में अधिक मानक है।
बेन वोइग्ट

2
और MSVC के नजरिए से, "मानक कॉलिंग कन्वेंशन" सिर्फ वही है जो आप से लेते हैं /Gd, /Gr, /Gv, /Gz। (यह कहना है, मानक कॉलिंग कन्वेंशन का उपयोग तब तक किया जाता है जब तक कि फ़ंक्शन डिक्लेरेशन स्पष्ट रूप से कॉलिंग कन्वेंशन को निर्दिष्ट नहीं करता है)। आप सोच रहे हैं __cdeclकि डिफ़ॉल्ट मानक कॉलिंग सम्मेलन कौन सा है।
एमएसल्टर्स

13

यह उन कार्यक्रमों के लिए बहुत सामान्य है जो आंशिक रूप से सी में लिखे गए हैं और आंशिक रूप से किसी अन्य भाषा में लिखे गए हैं (अक्सर विधानसभा भाषा, लेकिन कभी-कभी पास्कल, फोरट्रान, या कुछ और)। यह भी आम है कि कार्यक्रम में अलग-अलग लोगों द्वारा लिखे गए अलग-अलग घटक होते हैं जिनके पास हर चीज के लिए स्रोत कोड नहीं हो सकता है।

अधिकांश प्लेटफार्मों पर, एक विनिर्देश है - जिसे अक्सर एक एबीआई [एप्लीकेशन बाइनरी इंटरफ़ेस] कहा जाता है, जो बताता है कि एक कंपाइलर को किसी विशेष नाम के साथ एक फ़ंक्शन का उत्पादन करने के लिए क्या करना चाहिए जो कुछ विशेष प्रकार के तर्कों को स्वीकार करता है और कुछ विशेष प्रकार का मान लौटाता है। कुछ मामलों में, एक एबीआई एक से अधिक "कॉलिंग कन्वेंशन" को परिभाषित कर सकता है; ऐसी प्रणालियों के लिए संकलक अक्सर संकेत देने का साधन प्रदान करते हैं कि किसी विशेष कार्य के लिए किस सम्मेलन का उपयोग किया जाना चाहिए। उदाहरण के लिए, मैकिंटोश पर, अधिकांश टूलबॉक्स दिनचर्या पास्कल कॉलिंग कन्वेंशन का उपयोग करती हैं, इसलिए "लाइनटॉ" जैसी चीज़ के लिए प्रोटोटाइप कुछ इस तरह होगा:

/* Note that there are no underscores before the "pascal" keyword because
   the Toolbox was written in the early 1980s, before the Standard and its
   underscore convention were published */
pascal void LineTo(short x, short y);

यदि किसी परियोजना में सभी कोड एक ही संकलक का उपयोग करके संकलित किए गए थे, तो इससे कोई फर्क नहीं पड़ेगा कि प्रत्येक फ़ंक्शन के लिए संकलक किस नाम से निर्यात करता है, लेकिन कई स्थितियों में सी कोड के लिए उन फ़ंक्शनों को कॉल करना आवश्यक होगा जो अन्य टूल का उपयोग करके संकलित किए गए थे और वर्तमान संकलक के साथ recompiled नहीं किया जा सकता है [और बहुत अच्छी तरह से सी में भी नहीं हो सकता]। लिंकर नाम को परिभाषित करने में सक्षम होने के नाते इस तरह के कार्यों के उपयोग के लिए महत्वपूर्ण है।


हां, यही जवाब है। यदि यह सिर्फ C और C ++ है तो यह समझना मुश्किल है कि ऐसा क्यों किया जाता है। समझने के लिए हमें पुराने तरीके से जोड़ने के संदर्भ में चीजों को रखना चाहिए। स्टेटिक लिंकिंग विंडोज प्रोग्रामर के लिए आदिम लगता है लेकिन यह प्राथमिक कारण है कि C नाम नहीं रख सकता है
user34660

2
@ user34660: क्यूटी नहीं। यही कारण है कि C उन विशेषताओं के अस्तित्व को अनिवार्य नहीं कर सकता है जिनके क्रियान्वयन के लिए या तो निर्यात करने योग्य नामों की आवश्यकता होगी, या कई समान नाम वाले प्रतीकों के अस्तित्व की अनुमति देना जो माध्यमिक विशेषताओं द्वारा प्रतिष्ठित हैं।
सुपरकैट

क्या हम जानते हैं कि इस तरह की चीजों को "जनादेश" देने की कोशिश की गई थी या ऐसी चीजें C ++ से पहले C के लिए उपलब्ध थीं?
user34660

@ user34660: Re "स्टेटिक लिंकिंग विंडोज प्रोग्रामर्स के लिए आदिम लगता है ...", लेकिन डायनेमिक लिंकिंग कभी-कभी लिनक्स का उपयोग करने वाले लोगों के लिए एक प्रमुख PITA की तरह लगता है, जब प्रोग्राम X (शायद C ++ में लिखा गया है) को इंस्टाल करने का मतलब है नीचे ट्रैक करना और नए वर्जन को इंस्टॉल करना। पुस्तकालयों की जो आपके सिस्टम पर पहले से ही अलग-अलग संस्करण हैं।
jamesqf

@jamesqf, हां, यूनिक्स के पास विंडोज से पहले डायनेमिक लिंकिंग नहीं थी। मैं यूनिक्स / लिनक्स में डायनेमिक लिंकिंग के बारे में बहुत कम जानता हूं लेकिन ऐसा लगता है कि यह उतना सहज नहीं है जितना कि एक ऑपरेटिंग सिस्टम में हो सकता है।
user34660

12

मैं एक दूसरे उत्तर को जोड़ूंगा, जिसमें हुई कुछ स्पर्शरेखा चर्चाओं को संबोधित करने के लिए।

सी एबीआई (एप्लिकेशन बाइनरी इंटरफ़ेस) मूल रूप से रिवर्स ऑर्डर में स्टैक पर तर्क पारित करने के लिए कहा जाता है (यानी - दाएं से बाएं धक्का दिया जाता है), जहां कॉलर स्टैक स्टोरेज को भी मुक्त करता है। आधुनिक एबीआई वास्तव में तर्कों को पारित करने के लिए रजिस्टरों का उपयोग करता है, लेकिन कई मनमौजी विचार उस मूल स्टैक तर्क को पारित करते हैं।

इसके विपरीत, मूल पास्कल एबीआई ने तर्कों को बाएं से दाएं की ओर धकेल दिया, और कैली को तर्कों को पॉप करना पड़ा। मूल सी एबीआई दो महत्वपूर्ण बिंदुओं में मूल पास्कल एबीआई से बेहतर है। तर्क धक्का आदेश का अर्थ है कि पहले तर्क की स्टैक ऑफ़सेट को हमेशा ज्ञात किया जाता है, जिससे ऐसे कार्यों की अनुमति होती है जिनके पास अज्ञात संख्या में तर्क होते हैं, जहां शुरुआती तर्क यह नियंत्रित करते हैं कि अन्य तर्क कितने हैंprintf )।

दूसरा तरीका जिसमें सी एबीआई बेहतर है, कॉल करने वाले और कैली के मामले में व्यवहार कितने बेहतर हैं, इस पर सहमत नहीं हैं। सी मामले में, जब तक आप वास्तव में पिछले एक के तर्कों का उपयोग नहीं करते हैं, तब तक कुछ भी बुरा नहीं होता है। पास्कल में, गलत तर्कों को ढेर से पॉप किया जाता है, और पूरे स्टैक को दूषित किया जाता है।

मूल विंडोज 3.1 एबीआई पास्कल पर आधारित था। जैसे, इसने पास्कल एबीआई (बाएं से दाएं क्रम में, कैली पोप) में तर्क का इस्तेमाल किया। चूंकि तर्क संख्या में कोई भी बेमेल भ्रष्टाचार को रोकने के लिए नेतृत्व कर सकता है, एक प्रबंध योजना बनाई गई थी। प्रत्येक फ़ंक्शन नाम को उसके तर्कों के आकार, बाइट्स में इंगित करने वाली संख्या के साथ जोड़ दिया गया था। तो, 16 बिट मशीन पर, निम्न फ़ंक्शन (C सिंटैक्स):

int function(int a)

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

32 बिट विंडोज और इसके बाद stdcallएबीआई का उपयोग करें । यह पास्कल एबीआई के समान है, सिवाय पुश ऑर्डर सी की तरह है, दाएं से बाएं। पास्कल एबीआई की तरह, नामकरण करने वाला नाम ढेर भ्रष्टाचार से बचने के लिए फ़ंक्शन नाम में तर्क बाइट का आकार देता है।

यहां कहीं और किए गए दावों के विपरीत, सी एबीआई विजुअल स्टूडियो पर भी फ़ंक्शन के नाम को नहीं जोड़ता है। इसके विपरीत, stdcallएबीआई विनिर्देश के साथ सजाए गए कार्यों को वीएस के लिए अद्वितीय नहीं है। लिनक्स के लिए संकलन करते समय भी GCC इस ABI का समर्थन करता है। यह शराब द्वारा बड़े पैमाने पर उपयोग किया जाता है , यह लिनक्स लोड किए गए बायनेरिज़ को विंडोज़ संकलित DLLs से जोड़ने की अनुमति देने के लिए रन लोडर का उपयोग करता है।


9

C ++ कंपाइलर ओवरलोडेड फ़ंक्शंस के लिए अद्वितीय प्रतीक नामों की अनुमति देने के लिए नाम मैनबलिंग का उपयोग करते हैं जिनके हस्ताक्षर अन्यथा समान होंगे। यह मूल रूप से तर्कों के प्रकारों को भी एन्कोड करता है, जो फ़ंक्शन-आधारित स्तर पर बहुरूपता की अनुमति देता है।

C को इसकी आवश्यकता नहीं है क्योंकि यह कार्यों के ओवरलोडिंग की अनुमति नहीं देता है।

ध्यान दें कि नामकरण एक है (लेकिन निश्चित रूप से एकमात्र नहीं!) कारण है कि कोई 'C ++ ABI' पर भरोसा नहीं कर सकता है।


8

C ++ C कोड के साथ इंटरॉप करने में सक्षम होना चाहता है जो इसके खिलाफ लिंक करता है, या कि यह लिंक के खिलाफ है।

C गैर-नाम-आधारित फ़ंक्शन नामों की अपेक्षा करता है।

यदि C ++ ने इसे मंगवा लिया है, तो इसे C से निर्यातित गैर-मांगे हुए फ़ंक्शन नहीं मिलेंगे, या C को उन ++ फ़ंक्शंस का निर्यात नहीं मिलेगा। सी लिंकर को वह नाम प्राप्त करना होगा जो वह स्वयं अपेक्षा करता है, क्योंकि यह नहीं जानता कि यह सी ++ से आ रहा है या जा रहा है।


3

सी फ़ंक्शंस और वेरिएबल्स के नामों को मंगाने से लिंक समय पर उनके प्रकारों की जाँच की जा सकेगी। वर्तमान में, सभी (?) सी कार्यान्वयन आपको एक फ़ाइल में एक चर को परिभाषित करने और दूसरे में फ़ंक्शन के रूप में कॉल करने की अनुमति देते हैं। या आप एक गलत हस्ताक्षर के साथ एक फ़ंक्शन की घोषणा कर सकते हैं (जैसे void fopen(double)और फिर इसे कॉल करें।

मैंने 1991 में वापस चरवाहों के उपयोग के माध्यम से सी चर और कार्यों के प्रकार-सुरक्षित लिंकेज के लिए एक योजना प्रस्तावित की । इस योजना को कभी नहीं अपनाया गया, क्योंकि अन्य ने यहां उल्लेख किया है, यह पिछड़ी संगतता को नष्ट कर देगा।


1
आपका मतलब है " लिंक समय पर उनके प्रकारों की जांच करने की अनुमति दें "। प्रकारों को संकलन समय पर जांचा जाता है, लेकिन अनमैंगल्ड नामों के साथ लिंक करने से यह जांच नहीं हो सकती है कि विभिन्न संकलन इकाइयों में उपयोग की गई घोषणाएं सहमत हैं या नहीं। और अगर वे सहमत नहीं होते हैं, तो यह आपकी निर्माण प्रणाली है जो मौलिक रूप से टूट गई है और इसे ठीक करने की आवश्यकता है।
cmaster - मोनिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.