कार्यक्रम लिखित के रूप में मान्य है, लेकिन def.c
यह सुनिश्चित करने के लिए आवश्यक है कि कोड हमेशा सभी कंपाइलरों के साथ काम करता है और विभिन्न फ़ाइलों के लिए अनुकूलन स्तरों का संयोजन करता है।
$ nm def.o
0000000000000000 T foo
यही परिभाषा हमेशा चाहे कितना कि def.o
में मौजूद रहेंगे:
क्योंकि वहाँ extern
उस पर के साथ एक घोषणा है, def.c
समारोह foo()
, जो आप nm
साथ पुष्टि कर सकते हैं की एक बाहरी परिभाषा प्रदान करता है फ़ाइल संकलित है।
use.c
में एक इनलाइन परिभाषा foo()
की वहाँ है, लेकिन सी मानक में 6.7.4 के अनुसार यह अनिर्दिष्ट है foo()
करने के लिए कॉल कि इनलाइन परिभाषा का उपयोग करता है या एक बाहरी परिभाषा (व्यवहार में है कि क्या यह का उपयोग करता है का उपयोग करता है इनलाइन परिभाषा इस बात पर निर्भर करती है कि फ़ाइल अनुकूलित है या नहीं)। यदि संकलक इनलाइन परिभाषा का उपयोग करना चुनता है तो यह काम करेगा। यदि यह इनलाइन परिभाषा का उपयोग न करने का विकल्प चुनता है (उदा। क्योंकि इसे ऑप्टिमाइज़ेशन के बिना संकलित किया गया है) तो आपको किसी अन्य फ़ाइल में बाहरी परिभाषा की आवश्यकता है।
$ gcc -std=c99 -pedantic -Wall -Wextra -c -o use.o use.c
$ nm use.o
0000000000000000 T bar
U foo
लेकिन अनुकूलन के साथ ऐसा नहीं होता:
अनुकूलन use.o
बिना एक अपरिभाषित संदर्भ है
$ gcc -std=c99 -pedantic -Wall -Wextra -c -o use.o use.c -O3
$ nm use.o
0000000000000000 T bar
main.cpp
में foo()
की एक परिभाषा हो जाएगा, लेकिन यह आम तौर पर एक कमजोर उत्पन्न होगा प्रतीक, इसलिए यह किसी अन्य ऑब्जेक्ट में दूसरी परिभाषा पाई जाने पर लिंकर द्वारा नहीं रखा जा सकता है। कमजोर प्रतीक मौजूद है, तो यह है कि एक बाहरी परिभाषा की आवश्यकता है use.o
में किसी भी संभावित संदर्भ संतुष्ट कर सकते हैं, लेकिन अगर संकलक inlines main.o
में foo()
तो यह main.o
में foo()
के किसी भी परिभाषा उत्सर्जन नहीं हो सकता है, और इसलिए def.o
में परिभाषा अभी भी जरूरत होगी
$ g++ -std=c++11 -pedantic -Wall -Wextra -c -o main.o main.cpp
$ nm main.o
U bar
0000000000000000 W foo
0000000000000000 T main
U printf
हालांकि संकलन main.cpp
-O3
साथ foo
और वें के लिए कॉल inlines: use.o
को पूरा करने के अनुकूलन main.o
बिना एक कमजोर प्रतीक शामिल ई संकलक इसके लिए किसी भी प्रतीक उत्सर्जन नहीं:
$ g++ -std=c++11 -pedantic -Wall -Wextra -c -o main.o main.cpp -O3
$ nm main.o
U bar
0000000000000000 T main
U printf
तो अगर foo()
use.o
में inlined नहीं लेकिन तो main.o
में inlined है आप def.o
में बाहरी परिभाषा की जरूरत है सकते हैं यह है अगर def.c हटा दिया गया था और सी में foo का उपयोग नहीं किया गया था तो काम करें?
हां। यदि foo
केवल सी ++ फ़ाइल में उपयोग किया जाता है तो आपको foo
की def.o
में बाहरी परिभाषा की आवश्यकता नहीं है क्योंकि main.o
या तो अपनी स्वयं की (कमजोर) परिभाषा है या फ़ंक्शन को रेखांकित करेगी। foo.o
में परिभाषा केवल अन्य सी कोड से foo
पर गैर-इनलाइन कॉल को संतुष्ट करने की आवश्यकता है।
एक तरफ
: C++ कम्पाइलर जब main.o
के अनुकूलन foo
के लिए किसी भी प्रतीक पैदा क्योंकि सी ++ मानक का कहना है कि एक समारोह एक अनुवाद इकाई में inline
घोषित सभी अनुवाद इकाइयों में इनलाइन घोषित किया जाना चाहिए छोड़ करने की अनुमति दी है, और एक समारोह को कॉल करने के लिए inline
परिभाषा कॉल के समान फ़ाइल में उपलब्ध होना चाहिए। इसका मतलब है कि संकलक जानता है कि अगर कोई अन्य फ़ाइल foo()
पर कॉल करना चाहती है तो उस अन्य फ़ाइल में foo()
की परिभाषा होनी चाहिए, और इसलिए जब उस अन्य फ़ाइल को संकलित किया गया है तो संकलक फ़ंक्शन की एक और कमजोर प्रतीक परिभाषा उत्पन्न करने में सक्षम होगा (या जरूरत के रूप में इनलाइन)। main.o
में सभी कॉलों को रेखांकित किया गया है तो main.o
में foo
आउटपुट करने की आवश्यकता नहीं है।
इन सी, जहां use.c
में इनलाइन परिभाषा संकलक द्वारा अनदेखा किया जा सकता से differnet अर्थ विज्ञान रहे हैं, और def.o
में बाहरी परिभाषा भले ही def.c
में कुछ भी नहीं कहता मौजूद होना चाहिए।
क्या सी भी 'इनलाइन' कीवर्ड को पहचानता है? मैंने सोचा कि वे इसे अलग-अलग जादू करते हैं। –
@BenVoigt: हां, हालांकि इसमें थोड़ा अलग अर्थशास्त्र है। – Deduplicator
मुझे नहीं पता कि मैंने क्यों सोचा था कि सी संस्करण में कुछ अंडरस्कोर था। –