"स्थिर" और "स्थिर इनलाइन" फ़ंक्शन के बीच क्या अंतर है?


123

IMO दोनों ही फ़ंक्शन को केवल अनुवाद इकाई के दायरे के लिए बनाते हैं।

"स्थिर" और "स्थिर इनलाइन" फ़ंक्शन के बीच क्या अंतर है?

inlineहेडर फ़ाइल में क्यों रखा जाना चाहिए , फ़ाइल में नहीं .c?

जवाबों:


109

inlineसंकलक को निर्देश देता है कि वास्तविक कॉल को निष्पादित करने के बजाय फ़ंक्शन सामग्री को कॉलिंग कोड में एम्बेड करने का प्रयास करें।

छोटे कार्यों के लिए जिन्हें अक्सर कहा जाता है जो एक बड़ा प्रदर्शन अंतर बना सकते हैं।

हालाँकि, यह केवल एक "संकेत" है, और संकलक इसे अनदेखा कर सकता है, और अधिकांश संकलक अनुकूलन के भाग के रूप में भी, जब कीवर्ड संभव नहीं है, तो "इनलाइन" करने का प्रयास करेंगे।

उदाहरण के लिए:

static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};

यह तंग लूप प्रत्येक पुनरावृत्ति पर एक फ़ंक्शन कॉल करेगा, और फ़ंक्शन सामग्री वास्तव में उस कोड की तुलना में काफी कम है, जिसे कंपाइलर को कॉल करने के लिए डालने की आवश्यकता है। inlineअनिवार्य रूप से संकलक को निर्देश देगा कि वह कोड को एक समकक्ष में बदले:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

वास्तविक फ़ंक्शन कॉल को छोड़ना और वापस आना

जाहिर है कि यह एक उदाहरण है बिंदु को दिखाने के लिए, कोड का एक वास्तविक टुकड़ा नहीं।

staticगुंजाइश को संदर्भित करता है। सी में इसका मतलब है कि फ़ंक्शन / चर का उपयोग केवल उसी अनुवाद इकाई के भीतर किया जा सकता है।


4
नहीं, staticगुंजाइश को संदर्भित करता है। सी में इसका मतलब है कि फ़ंक्शन / चर का उपयोग केवल उसी अनुवाद इकाई के भीतर किया जा सकता है।
littleadv

8
यह नोट करना भी महत्वपूर्ण है कि इनलाइन के रूप में घोषित कोड हेडर में है, जहाँ सामान्य (गैर-टेम्पलेट) स्रोत कोड हेडर में कई पुनर्निर्देशन त्रुटियों को उत्पन्न किए बिना नहीं जा सकता है। इसलिए जब कुछ इनलाइन घोषित किया जाता है, भले ही कंपाइलर इसे इनलाइन नहीं करता है, फिर भी एक मानक-
जनादेशित

13
@VoidStar वास्तव में static(साथ या बिना inline) हेडर में पूरी तरह से अच्छी तरह से हो सकता है, बिना कारण देखें। टेम्प्लेट C ++ के लिए है, यह प्रश्न C. के बारे में है
littleadv

2
@littleadv: हेडर फाइल्स में फंक्शन डेफिनिशन डालने का मुख्य कारण उन्हें अयोग्य बनाना है, इसलिए उन्हें स्पष्ट रूप inlineसे चिन्हित करना अच्छी शैली है, इमो
क्रिस्टोफ

9
वास्तव में संकलक को निर्देशinline नहीं देता है कि वह इनलाइनिंग में कोई प्रयास न करे। यह केवल प्रोग्रामर को ओडीआर उल्लंघन के बिना कई अनुवाद इकाइयों में फ़ंक्शन बॉडी को शामिल करने देता है। इसका एक पक्ष प्रभाव यह है कि यह संकलक के लिए संभव बनाता है, जब यह फ़ंक्शन को इनलाइन करता है, वास्तव में ऐसा करने के लिए।
रुस्लान

96

डिफ़ॉल्ट रूप से, इनलाइन परिभाषा केवल वर्तमान अनुवाद इकाई में मान्य है।

यदि संग्रहण वर्ग है extern, तो पहचानकर्ता के पास बाहरी लिंकेज है और इनलाइन परिभाषा बाहरी परिभाषा भी प्रदान करती है।

यदि संग्रहण वर्ग है static, तो पहचानकर्ता के पास आंतरिक लिंकेज है और इनलाइन परिभाषा अन्य अनुवाद इकाइयों में अदृश्य है।

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

जैसा कि संकलक इनलाइन (और इनलाइन नहीं) के लिए स्वतंत्र है, जिसकी परिभाषा वर्तमान अनुवाद इकाई में दिखाई देती है (और, लिंक-टाइम अनुकूलन के लिए धन्यवाद, यहां तक ​​कि विभिन्न अनुवाद इकाइयों में भी, हालांकि सी मानक वास्तव में खाता नहीं है वह), अधिकांश व्यावहारिक उद्देश्यों के लिए, staticऔर static inlineफ़ंक्शन परिभाषाओं के बीच कोई अंतर नहीं है ।

inlineविनिर्देशक (जैसे registerभंडारण वर्ग) केवल एक संकलक संकेत है, और संकलक पूरी तरह से इसे अनदेखा करने के लिए स्वतंत्र है। मानकों का पालन करने वाले गैर-अनुकूलन वाले कंपाइलरों को केवल उनके दुष्प्रभावों का सम्मान करना पड़ता है, और संकलक का अनुकूलन इन संकेतों को स्पष्ट संकेतों के साथ या बिना करेगा।

inlineऔर registerबेकार नहीं हैं, हालांकि, जब वे प्रोग्रामर कोड लिखने वाले त्रुटियों को फेंकने के लिए कंपाइलर को निर्देश देते हैं, जो अनुकूलन को असंभव बना देगा: एक inlineआंतरिक परिभाषा आंतरिक लिंकेज के साथ पहचानकर्ताओं का संदर्भ नहीं दे सकती है (क्योंकि ये एक अलग अनुवाद इकाई में अनुपलब्ध होगा) या स्थैतिक भंडारण अवधि के साथ परिवर्तनीय स्थानीय चर को परिभाषित करें (जैसा कि ये राज्य अनुवाद इकाइयों को साझा नहीं करेंगे), और आप register-qualified चर के पते नहीं ले सकते ।

व्यक्तिगत रूप से, मैं सम्मेलन का उपयोग staticहेडर के भीतर फ़ंक्शन परिभाषाओं को चिह्नित करने के लिए भी करता हूं inline, क्योंकि हेडर फ़ाइलों में फ़ंक्शन परिभाषाओं को डालने का मुख्य कारण उन्हें निष्प्रभावी बनाना है।

सामान्य तौर पर, मैं केवल हेडर के भीतर घोषणाओं के अलावा static inlineफ़ंक्शन और static constऑब्जेक्ट परिभाषाओं का उपयोग करता हूं extern

मैंने कभी भी inlineस्टोरेज क्लास से अलग एक फंक्शन नहीं लिखा है static


8
यह सही जवाब है। किसी भी उत्तर के बारे inlineमें बात करना जैसे कि यह वास्तव में इनलाइनिंग लागू किया गया है भ्रामक और यकीनन गलत है। कोई भी आधुनिक संकलक इसे एक इनलाइन के संकेत के रूप में उपयोग नहीं करता है या किसी फ़ंक्शन की इनलाइनिंग को सक्षम करने के लिए इसकी आवश्यकता होती है।
Tyg13

1
"हेडर इनलाइन में स्थिर फ़ंक्शन परिभाषाओं को चिह्नित करने के लिए कन्वेंशन का उपयोग करें" के लिए upvoted।
जॉन जेड। ली

मैं अपने पूरे जवाब पढ़ सकते हैं और मैं अभी भी बीच अर्थ अंतर नहीं मिलता है staticऔर static inline। ये दोनों अन्य अनुवाद इकाइयों के लिए परिभाषा को अदृश्य बनाते हैं। तो static inlineइसके बजाय लिखने का एक समझदार कारण क्या होगा static?
user541686

21

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

इस प्रकार मुझे लगता है कि staticअनुवाद इकाइयों में इस्तेमाल किया जाना चाहिए और अतिरिक्त चेक कंपाइलर से लाभ का उपयोग अप्रयुक्त कार्यों को खोजने के लिए किया जाता है। और static inlineचेतावनी जारी किए बिना फ़ंक्शंस (बाहरी लिंकेज की अनुपस्थिति के कारण) हो सकने वाले कार्य प्रदान करने के लिए हेडर फ़ाइलों में उपयोग किया जाना चाहिए।

दुर्भाग्य से मुझे उस तर्क के लिए कोई सबूत नहीं मिला। यहां तक ​​कि जीसीसी प्रलेखन से मैं यह निष्कर्ष निकालने में सक्षम नहीं था कि inlineअप्रयुक्त फ़ंक्शन चेतावनियों को रोकता है। अगर किसी का वर्णन करने के लिए लिंक साझा करेंगे, तो मैं सराहना करूँगा।


1
मिमी, अभी भी warning: unused function 'function' [clang-diagnostic-unused-function]एक static inlineफ़ंक्शन के लिए मिला जब clang-tidy(v8.0.1) के साथ निर्माण किया गया, जिसका उपयोग किसी अन्य अनुवाद इकाई में किया जाता है। लेकिन निश्चित रूप से, यह सबसे अच्छा स्पष्टीकरण और संयोजन के लिए कारण में से एक है staticऔर inline!
12

6

C में, staticआपके द्वारा परिभाषित फंक्शन या वैरिएबल का उपयोग केवल इस फ़ाइल में किया जा सकता है (अर्थात संकलन इकाई)

तो, static inlineइनलाइन फ़ंक्शन का मतलब है जो केवल इस फ़ाइल में उपयोग किया जा सकता है।

संपादित करें:

संकलन इकाई का अनुवाद इकाई होना चाहिए


2
या फैंसी शब्दों में: इसका आंतरिक संबंध है।
के-बैलो

@AlokSave: संकलन इकाई और अनुवाद इकाई के बीच अंतर है ? यदि हां, तो C ++ भाषा के संदर्भ में कौन अधिक उपयुक्त है?
लीजेंड्स 2k

मेरा मानना the compile unitहै कि कुछ ऐसा है जो मैंने गलती से लिखा है, ऐसी कोई बात नहीं है, वास्तविक शब्दावली हैtranslation unit
shengy

आपका उत्तर पूर्ण नहीं है क्योंकि इसका उपयोग अधिकतर हेडर फ़ाइलों, अनुवाद इकाइयों में किया जाता है।
12

5

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


inlineपरिभाषा में उपयोग के बारे में क्या ? क्या आप भी externकार्यों के लिए इसका इस्तेमाल नहीं करते हैं ?
new_perl

क्या यह जीसीसी के हालिया संस्करण के साथ अभी भी सही है? यदि आप एक उदाहरण और जीसीसी के कौन से संस्करण को सूचीबद्ध करते हैं तो आपका उत्तर बहुत अधिक दिलचस्प होगा।
जेड बोसोन

@Zboson: मेरे पास वह जानकारी आसानी से उपलब्ध नहीं है और इस समय बहुत से जीसीसी संस्करणों को सेटअप और परीक्षण करने का समय नहीं है, लेकिन मैं मानता हूं कि यह उपयोगी जानकारी होगी। आप शायद तब पा सकते हैं जब gcc ने पहले अप्रयुक्त स्थिर कार्यों / वस्तुओं का अनुकूलन शुरू कर दिया है attribute((used))और इसके उपयोग को अन्यथा असंबद्ध staticकार्यों और डेटा को संदर्भित करने की अनुमति देता है ।
आर .. गिटहब स्टॉप हेल्पिंग ICE
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.