C फ़ंक्शन पर बाहरी कीवर्ड का प्रभाव


171

सी में, मैंने externफ़ंक्शन घोषणा से पहले उपयोग किए गए कीवर्ड के किसी भी प्रभाव को नहीं देखा । सबसे पहले, मैंने सोचा कि जब extern int f();एक फ़ाइल में परिभाषित करना आपको फ़ाइल के दायरे से बाहर इसे लागू करने के लिए मजबूर करता है। हालाँकि मुझे पता चला कि दोनों:

extern int f();
int f() {return 0;}

तथा

extern int f() {return 0;}

संकलित ठीक है, जीसीसी से कोई चेतावनी के साथ। मैंने उपयोग किया gcc -Wall -ansi; यह भी //टिप्पणियों को स्वीकार नहीं करेगा ।

extern फ़ंक्शन परिभाषाओं से पहले उपयोग करने के लिए कोई प्रभाव हैं ? या यह सिर्फ एक वैकल्पिक खोजशब्द है जिसमें कार्यों के लिए कोई साइड इफेक्ट नहीं है।

बाद के मामले में मुझे समझ में नहीं आता है कि मानक डिजाइनरों ने व्याकरण को शानदार खोजशब्दों के साथ चुनने के लिए क्यों चुना।

संपादित करें: स्पष्ट करने के लिए, मुझे पता है कि externचर में उपयोग होता है, लेकिन मैं केवल कार्यों के बारे externमें पूछ रहा हूं ।


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

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

@ ईडी .. अगर वाष्पशील int foo foo.c में एक वैश्विक है, और bar.c को इसकी आवश्यकता है, तो bar.c को इसे बाहरी घोषित करना चाहिए। इसके फायदे हैं। इसके अलावा, आपको कुछ फ़ंक्शन साझा करने की आवश्यकता हो सकती है जिन्हें आप सार्वजनिक शीर्ष लेख में उजागर नहीं करना चाहते हैं।
टिम पोस्ट


2
@Barry यदि बिल्कुल, अन्य प्रश्न इस एक का एक डुप्लिकेट है। 2009 बनाम 2012
एलाजार लीबोविच

जवाबों:


138

हमारे पास दो फाइलें हैं, foo.c और bar.c.

यहाँ foo.c है

#include <stdio.h>

volatile unsigned int stop_now = 0;
extern void bar_function(void);

int main(void)
{
  while (1) {
     bar_function();
     stop_now = 1;
  }
  return 0;
}

अब, यहाँ bar.c है

#include <stdio.h>

extern volatile unsigned int stop_now;

void bar_function(void)
{
   while (! stop_now) {
      printf("Hello, world!\n");
      sleep(30);
   }
}

जैसा कि आप देख सकते हैं, हमारे पास foo.c और bar.c के बीच कोई साझा हैडर नहीं है, हालांकि bar.c को foo.c में घोषित कुछ की जरूरत है जब यह जुड़ा हुआ है, और foo.c को लिंक होने पर bar.c से एक फ़ंक्शन की आवश्यकता होती है।

'बाहरी' का उपयोग करके, आप संकलक को बता रहे हैं कि जो कुछ भी होगा वह लिंक समय पर (गैर-स्थिर) मिलेगा; वर्तमान पास में इसके लिए कुछ भी आरक्षित न करें क्योंकि बाद में इसका सामना करना पड़ेगा। इस संबंध में कार्य और चर समान रूप से व्यवहार किए जाते हैं।

यह बहुत उपयोगी है यदि आपको मॉड्यूल के बीच कुछ वैश्विक साझा करने की आवश्यकता है और इसे हेडर में डालना / प्रारंभ करना नहीं चाहते हैं।

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

उपरोक्त उदाहरण में, मुख्य () केवल एक बार हैलो वर्ल्ड प्रिंट करेगा, लेकिन बार_फंक्शन () में प्रवेश करना जारी रखें। यह भी ध्यान दें, bar_function () इस उदाहरण में वापस नहीं जा रहा है (क्योंकि यह सिर्फ एक सरल उदाहरण है)। अगर यह पर्याप्त रूप से व्यावहारिक नहीं लगता है, तो एक संकेत (इसलिए, अस्थिर) सेवित होने पर stop_now संशोधित होने की कल्पना करें।

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

उम्मीद है की वो मदद करदे :)


56
आपका कोड बार_फंक्शन से पहले बाहरी के बिना ठीक संकलित करेगा।
एलाजार लीबोविच

2
@ समय: फिर आपके पास मेरे द्वारा काम किए गए कोड के साथ काम करने का संदिग्ध विशेषाधिकार नहीं है। यह हो सकता है। कभी-कभी शीर्ष लेख में स्थिर फ़ंक्शन परिभाषा भी होती है। यह बदसूरत है, और अनावश्यक 99.99% समय है (मैं एक आदेश या दो या परिमाण द्वारा बंद हो सकता है, यह दर्शाता है कि यह कितनी बार आवश्यक है)। यह आमतौर पर तब होता है जब लोग यह गलत समझ लेते हैं कि हेडर की जरूरत तभी होती है जब अन्य स्रोत फाइलें सूचना का उपयोग करेंगी; हेडर एक स्रोत फ़ाइल के लिए घोषणा जानकारी संग्रहीत करने के लिए उपयोग किया जाता है (ab) और किसी अन्य फ़ाइल को इसमें शामिल करने की उम्मीद नहीं है। कभी-कभी, यह अधिक विपरीत कारणों से होता है।
जोनाथन लेफ़लर

2
@ जोनाथन लेफ़लर - वास्तव में डब! मुझे कुछ पहले स्केच कोड विरासत में मिले हैं, लेकिन मैं ईमानदारी से कह सकता हूं कि मैंने कभी किसी को हेडर में स्थिर घोषणा नहीं दी। ऐसा लगता है कि आप एक नहीं बल्कि मजेदार और दिलचस्प काम है, हालांकि :)
टिम पोस्ट

1
'हेडर में फंक्शन प्रोटोटाइप नहीं' का नुकसान यह है कि आपको फ़ंक्शन डेफिनेशन bar.cऔर इन डिक्लेरेशन के बीच निरंतरता की स्वचालित स्वतंत्र जाँच नहीं मिलती है foo.c। यदि फ़ंक्शन में घोषित किया गया है foo.h और दोनों फ़ाइलों में शामिल हैं foo.h, तो हेडर दो स्रोत फ़ाइलों के बीच संगतता को लागू करता है। इसके बिना, यदि परिवर्तन की परिभाषा लेकिन घोषणा bar_functionमें bar.cपरिवर्तन foo.cनहीं किया गया है, तो रन-टाइम में चीजें गलत हो जाती हैं; संकलक समस्या को हाजिर नहीं कर सकता। हेडर ठीक से उपयोग किए जाने के साथ, कंपाइलर समस्या को स्पॉट करता है।
जोनाथन लेफ्लर 21

1
फ़ंक्शंस की घोषणाओं पर बाहरी 'अहस्ताक्षरित int' में 'int' की तरह शानदार है। जब प्रोटोटाइप एक फॉरवर्ड डिक्लेरेशन नहीं है, तो 'एक्सटरन' का उपयोग करना अच्छा है ... लेकिन जब तक कि यह कार्य एक किनारे का मामला न हो, तब तक इसे 'एक्सटरन' के बिना हेडर में रहना चाहिए। stackoverflow.com/questions/10137037/…

82

जहां तक ​​मुझे मानक याद है, सभी फ़ंक्शन घोषणाओं को डिफ़ॉल्ट रूप से "बाहरी" माना जाता है, इसलिए इसे स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता नहीं है।

यह इस खोजशब्द को बेकार नहीं बनाता है क्योंकि इसका उपयोग चर के साथ भी किया जा सकता है (और यह मामला है - यह लिंकेज समस्याओं को हल करने का एकमात्र उपाय है)। लेकिन कार्यों के साथ - हाँ, यह वैकल्पिक है।


21
तब मानक डिजाइनर के रूप में मैं करता हूँ की अनुमति नहीं देने , कार्यों के साथ निर्वासन का उपयोग कर के रूप में यह सिर्फ व्याकरण के लिए शोर कहते हैं।
एलाजार लीबोविच

3
पश्चगामी संगतता दर्द हो सकती है।
मथुसम मट

1
@ElazarLeibovich वास्तव में, इस विशेष मामले में, इसे अस्वीकार करने से व्याकरण में शोर बढ़ेगा।
ऑर्बिट

1
कैसे एक कीवर्ड सीमित कहते हैं शोर मुझे परे है, लेकिन मुझे लगता है कि यह स्वाद की बात है।
एलज़ार लीबोविच

हालांकि कार्यों के लिए "बाहरी" के उपयोग की अनुमति देना उपयोगी है, क्योंकि यह अन्य प्रोग्रामर को इंगित करता है कि फ़ंक्शन किसी अन्य फ़ाइल में परिभाषित किया गया है, वर्तमान फ़ाइल में नहीं है और शामिल हेडर में से एक में भी घोषित नहीं किया गया है।
डिंप

23

आपको दो अलग-अलग अवधारणाओं के बीच अंतर करने की आवश्यकता है: फ़ंक्शन परिभाषा और प्रतीक घोषणा। "एक्सटर्न" एक लिंकेज संशोधक है, जो संकलक के लिए एक संकेत है जहां बाद में संदर्भित प्रतीक परिभाषित किया गया है (संकेत है, "यहां नहीं")।

अगर मैं लिखता

extern int i;

फ़ाइल स्कोप में (एक फंक्शन ब्लॉक के बाहर) सी फाइल में, फिर आप कह रहे हैं "वेरिएबल को कहीं और परिभाषित किया जा सकता है"।

extern int f() {return 0;}

फ़ंक्शन f की एक घोषणा और फ़ंक्शन f की परिभाषा दोनों है। इस मामले में परिभाषा बाहरी पर सवारी करती है।

extern int f();
int f() {return 0;}

पहले एक घोषणा है, उसके बाद परिभाषा है।

externयदि आप घोषित करना चाहते हैं और एक साथ फ़ाइल स्कोप वैरिएबल को परिभाषित करना चाहते हैं तो इसका उपयोग गलत है। उदाहरण के लिए,

extern int i = 4;

संकलक के आधार पर एक त्रुटि या चेतावनी देगा।

का उपयोग externयदि आप स्पष्ट रूप से किसी चर की परिभाषा से बचना चाहते हैं तो इसका उपयोगी है।

मुझे समझाने दो:

मान लें कि फ़ाइल एसी में है:

#include "a.h"

int i = 2;

int f() { i++; return i;}

फ़ाइल आह में शामिल हैं:

extern int i;
int f(void);

और फ़ाइल bc में शामिल है:

#include <stdio.h>
#include "a.h"

int main(void){
    printf("%d\n", f());
    return 0;
}

हेडर में बाहरी उपयोगी है, क्योंकि यह लिंक चरण के दौरान संकलक को बताता है, "यह एक घोषणा है, और परिभाषा नहीं है"। अगर मैं एसी को लाइन में हटाता हूं जो i को परिभाषित करता है, तो इसके लिए जगह आवंटित करता है और इसके लिए एक मान प्रदान करता है, प्रोग्राम को एक अपरिभाषित संदर्भ के साथ संकलन करने में विफल होना चाहिए। यह डेवलपर को बताता है कि उसने एक चर का उल्लेख किया है, लेकिन अभी तक इसे परिभाषित नहीं किया है। यदि दूसरी ओर, मैं "बाहरी" कीवर्ड को छोड़ देता हूं, और हटा देता हूंint i = 2 लाइन को , तो प्रोग्राम अभी भी संकलित करता है - मुझे 0 के डिफ़ॉल्ट मान के साथ परिभाषित किया जाएगा।

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

फ़ंक्शन के लिए, फ़ंक्शन घोषणाओं में, कीवर्ड वास्तव में अनावश्यक है। फंक्शन घोषणाओं में निहित परिभाषा नहीं होती है।


क्या आपको int i = 2-3 वें पैराग्राफ में लाइन हटाने का मतलब है ? और क्या यह बताना सही है int i;, कि संकलक उस चर के लिए मेमोरी आवंटित करेगा, लेकिन यह देखते हुए extern int i;, संकलक मेमोरी आवंटित नहीं करेगा, लेकिन चर के लिए कहीं और खोज करेगा?
फ्रोजन फ्लेम

वास्तव में यदि आप "बाहरी" कीवर्ड को छोड़ देते हैं तो यह प्रोग्राम एसी और बीसी (आईएच के कारण) में पुन: परिभाषित करने के कारण संकलित नहीं करेगा।
निक्ट

15

externकीवर्ड परिवेश के आधार पर अलग अलग रूपों पर ले जाता है। यदि एक घोषणा उपलब्ध है, तो externकीवर्ड अनुवाद इकाई में पहले से निर्दिष्ट लिंकेज लेता है। ऐसी किसी भी घोषणा के अभाव में, externबाहरी संबंध निर्दिष्ट करता है।

static int g();
extern int g(); /* g has internal linkage */

extern int j(); /* j has tentative external linkage */

extern int h();
static int h(); /* error */

यहाँ C99 ड्राफ्ट (n1256) से संबंधित पैराग्राफ हैं:

6.2.2 पहचानकर्ताओं के लिंक

[...]

4 एक पहचानकर्ता के लिए स्टोरेज-क्लास निर्दिष्ट बाहरी के साथ उस दायरे में घोषित किया जाता है जिसमें उस पहचानकर्ता की एक पूर्व घोषणा दिखाई देती है, 23) यदि पूर्व घोषणा आंतरिक या बाहरी लिंकेज को निर्दिष्ट करती है, तो पहचानकर्ता का जुड़ाव बाद के विवरण में समान है पूर्व घोषणा में निर्दिष्ट लिंकेज के रूप में। यदि कोई पूर्व घोषणा दिखाई नहीं देती है, या यदि पूर्व घोषणा कोई लिंकेज निर्दिष्ट नहीं करती है, तो पहचानकर्ता के पास बाहरी लिंकेज है।

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


क्या यह मानक है, या आप मुझे केवल एक ठेठ संकलक का व्यवहार बता रहे हैं? मानक के मामले में, मुझे मानक के लिंक के लिए खुशी होगी। लेकिन धन्यवाद!
एलाजार लीबोविच

यह मानक व्यवहार है। C99 ड्राफ्ट यहां उपलब्ध है: < open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf >। हालांकि वास्तविक मानक मुक्त नहीं है (अधिकांश उद्देश्यों के लिए मसौदा पर्याप्त है)।
dirkgently

1
मैंने अभी इसे gcc में परीक्षण किया है और यह दोनों "extern int h (); static int h () {return 0;}" और "int h (); static int h () {return 0;}" के साथ स्वीकार किए जाते हैं। चेतावनी। क्या यह केवल C99 है और ANSI नहीं है? क्या आप मुझे ड्राफ्ट में सटीक अनुभाग का उल्लेख कर सकते हैं, क्योंकि यह gcc के लिए सही नहीं लगता है।
एलाजार लीबोविच

फिर से जांचें। मैंने gcc 4.0.1 के साथ भी यही कोशिश की और मुझे एक त्रुटि मिली कि यह कहाँ होना चाहिए। यदि आपके पास अन्य संकलक तक पहुंच नहीं है, तो comeau के ऑनलाइन कंपाइलर या codepad.org को देखें। मानक पढ़ें।
dirkgently

2
@dirkgently, मेरा असली सवाल यह है कि फंक्शन डिक्लेरेशन के साथ एक्सट्रॉन का उपयोग करने के लिए कोई प्रभाव पड़ता है, और यदि कोई नहीं है तो फंक्शन डिक्लेरेशन में एक्सटर्नल को जोड़ना क्यों संभव है। और जवाब नहीं है, कोई प्रभाव नहीं है, और एक बार नहीं-तो-मानक संकलक के साथ एक प्रभाव था।
एलजार लीबोविच

11

इनलाइन फ़ंक्शंस के विशेष नियम हैं, जिनका externअर्थ है। (ध्यान दें कि इनलाइन फ़ंक्शन C99 या GNU एक्सटेंशन हैं; वे मूल C में नहीं थे।

गैर-इनलाइन कार्यों के लिए, extern इसकी आवश्यकता नहीं है क्योंकि यह डिफ़ॉल्ट रूप से चालू है।

ध्यान दें कि C ++ के नियम अलग हैं। उदाहरण के लिए, extern "C"C ++ के C ++ घोषणा पर आवश्यक है जिसे आप C ++ से कॉल करने जा रहे हैं, और इसके बारे में अलग-अलग नियम हैं inline


यहाँ केवल यही उत्तर है कि दोनों सही हैं और वास्तव में प्रश्न का उत्तर देते हैं।
रोबिंजम

4

IOW, बाहरी अतिरेक है, और कुछ भी नहीं करता है।

इसीलिए, 10 साल बाद:

देखें ad6dad0 प्रतिबद्ध , b199d71 प्रतिबद्ध , प्रतिबद्ध 5,545,442 (29 अप्रैल 2019) से डेंटन लियू ( Denton-L)
(द्वारा विलय Junio सी Hamano - gitster- में प्रतिबद्ध 4aeeef3 , 13 मई 2019)

*.[ch]: externका उपयोग कर समारोह घोषणाओं से हटा देंspatch

externफ़ंक्शन की घोषणाओं को हटाने के लिए एक धक्का दिया गया है ।

externफ़ंक्शन घोषणाओं के लिए " " के कुछ उदाहरणों को हटा दें जो कोकीनले द्वारा पकड़े गए हैं।
ध्यान दें कि Coccinelle को प्रसंस्करण कार्यों के साथ __attribute__या varargs के साथ कुछ कठिनाई है इसलिए कुछ externघोषणाओं को भविष्य के पैच में निपटाए जाने के लिए छोड़ दिया जाता है।

यह Coccinelle पैच इस्तेमाल किया गया था:

  @@
    type T;
    identifier f;
    @@
    - extern
    T f(...);

और इसके साथ चलाया गया था:

  $ git ls-files \*.{c,h} |
    grep -v ^compat/ |
    xargs spatch --sp-file contrib/coccinelle/noextern.cocci --in-place

यह हमेशा सीधा नहीं है, हालांकि:

डेंटन लियू ( ) द्वारा देखें 7027f50 (04 सितंबर 2019) प्रतिबद्ध(द्वारा विलय डेंटन लियू - - में प्रतिबद्ध 7027f50 , 05 सितं, 2019)Denton-L
Denton-L

compat/*.[ch]: externस्पैच का उपयोग करके फ़ंक्शन घोषणाओं से हटाएं

5545442 ( *.[ch]: externस्पैच, 2019-04-29, Git v2.22.0-rc0 का उपयोग करके फ़ंक्शन घोषणाओं से हटाएं) में, हमने फ़ंक्शन घोषणाओं से एक्सटर्न्स का उपयोग करके हटा दिया, spatchलेकिन हमने जानबूझकर फ़ाइलों को बाहर रखाcompat/ क्योंकि कुछ को सीधे एक अपस्ट्रीम से कॉपी किया जाता है और हमें बचना चाहिए उन्हें मंथन करना ताकि भविष्य के अपडेट को मैन्युअल रूप से मर्ज करना सरल हो जाएगा।

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

यह Coccinelle पैच इस्तेमाल किया गया था:

@@
type T;
identifier f;
@@
- extern
  T f(...);

और इसके साथ चलाया गया था:

$ git ls-files compat/\*\*.{c,h} |
    xargs spatch --sp-file contrib/coccinelle/noextern.cocci --in-place
$ git checkout -- \
    compat/regex/ \
    compat/inet_ntop.c \
    compat/inet_pton.c \
    compat/nedmalloc/ \
    compat/obstack.{c,h} \
    compat/poll/

Coccinelle के साथ काम करने में __attribute__थोड़ी परेशानी होती है और varargs तो हम निम्नलिखित सुनिश्चित करने के लिए भागते हैं कि कोई शेष परिवर्तन पीछे न रह जाए:

$ git ls-files compat/\*\*.{c,h} |
    xargs sed -i'' -e 's/^\(\s*\)extern \([^(]*([^*]\)/\1\2/'
$ git checkout -- \
    compat/regex/ \
    compat/inet_ntop.c \
    compat/inet_pton.c \
    compat/nedmalloc/ \
    compat/obstack.{c,h} \
    compat/poll/

ध्यान दें कि Git 2.24 (Q4 2019) के साथ, किसी भी स्थान externको गिरा दिया जाता है।

एमिली शफ़र ( ) द्वारा प्रतिबद्ध 65904b8 (30 सितंबर 2019) देखें । मदद-द्वारा: जेफ किंग ( )डेंटन लियू ( ) द्वारा प्रतिबद्ध 8464f94 (21 सितंबर 2019) देखें । मदद-द्वारा: जेफ किंग ( )( जूनियो सी हमानो द्वारा विलय - - ५बी १ ९बीसी , ० 07 अक्टूबर २०१ ९ में)nasamuffin
peff
Denton-L
peff
gitster

promisor-remote.h: externफ़ंक्शन घोषणा से ड्रॉप

इस फ़ाइल के निर्माण के दौरान, हर बार एक नई फ़ंक्शन घोषणा पेश की गई थी, इसमें ए शामिल था extern
हालाँकि, 5545442 से शुरू ( *.[ch]: 2019-04-29, Git v2.22.0-rc0 externका उपयोग करके फ़ंक्शन घोषणाओं को हटा दें spatch), हम बाहरी रूप से बाहरी लोगों को फ़ंक्शन घोषणाओं में उपयोग होने से रोकने के लिए सक्रिय रूप से प्रयास कर रहे हैं क्योंकि वे अनावश्यक हैं।

इन नकली externएस निकालें ।


3

externकीवर्ड सूचित संकलक समारोह या चर बाहरी संबंध है - दूसरे शब्दों में, यह है कि यह एक है जिसमें यह परिभाषित किया गया है के अलावा अन्य फ़ाइलों से दिख रहा है। इस अर्थ में यह staticकीवर्ड के विपरीत अर्थ है । externपरिभाषा के समय लगाना थोड़ा अजीब है , क्योंकि किसी भी अन्य फाइल में परिभाषा की दृश्यता नहीं होगी (या इसके परिणामस्वरूप कई परिभाषाएँ होंगी)। आम तौर पर आप externबाहरी दृश्यता (जैसे हेडर फ़ाइल) के साथ किसी बिंदु पर एक घोषणा में डालते हैं और परिभाषा कहीं और डालते हैं।


2

फंक्शन एक्सटर्नल घोषित करने का अर्थ है कि इसकी परिभाषा लिंकिंग के समय हल हो जाएगी, संकलन के दौरान नहीं।

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

मुझे नहीं लगता कि ऐसा करना बहुत उपयोगी होगा लेकिन इस तरह के प्रयोग करने से भाषा के संकलक और लिंकर के काम करने के तरीके के बारे में बेहतर जानकारी मिलती है।


2
IOW, बाहरी अतिरेक है, और कुछ भी नहीं करता है। यह बहुत स्पष्ट होगा यदि आप इसे इस तरह से रखते हैं।
एलजार लीबोविच

@ElazarLeibovich मैं सिर्फ हमारे कोडबेस में इसी तरह के मामले का सामना करता था और उसी निष्कर्ष पर पहुंचा था। यहाँ उत्तर के माध्यम से उन सभी को आपके एक लाइनर में अभिव्यक्त किया जा सकता है। इसका कोई व्यावहारिक प्रभाव नहीं है लेकिन पठनीयता के लिए अच्छा हो सकता है। आपको ऑनलाइन देखकर अच्छा लगा न कि सिर्फ मीटअप में :)
अवीव

1

इसका कोई प्रभाव नहीं पड़ता है क्योंकि लिंक-टाइम पर लिंकर बाहरी परिभाषा (आपके मामले में extern int f()) को हल करने की कोशिश करता है । इससे कोई फर्क नहीं पड़ता कि यह एक ही फाइल या एक अलग फाइल में मिलता है, जब तक यह पाया जाता है।

उम्मीद है कि यह आपके प्रश्न का उत्तर देगा।


1
फिर externकिसी भी समारोह में जोड़ने की अनुमति क्यों ?
एलजार लीबोविच

2
कृपया अपने पोस्ट में असंबंधित स्पैम रखने से बचें। धन्यवाद!
मैक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.