C में "स्थिर" फ़ंक्शन क्या है?


505

सवाल सीधे सादे का था कार्य, नहीं static तरीके, जैसा कि टिप्पणियों में स्पष्ट किया गया है।

मैं समझता हूं कि एक staticचर क्या है, लेकिन एक staticफ़ंक्शन क्या है ?

और ऐसा क्यों है कि अगर मैं एक फ़ंक्शन की घोषणा करता हूं, तो आइए, हम कहते हैं void print_matrixकि a.c(बिना a.h) और शामिल करें "a.c"- मुझे मिलता है "print_matrix@@....) already defined in a.obj", लेकिन अगर मैं इसे घोषित करता हूं static void print_matrixतो यह संकलित करता है?

अद्यतन केवल चीजों को साफ करने के लिए - मुझे पता है कि इसमें .cबुरा भी है, जैसा कि आप में से कई ने बताया है। मैं बस इसे अस्थायी रूप से खाली करने के लिए करता main.cहूं , जब तक कि मुझे उन सभी कार्यों को उचित .hऔर .cफाइलों में समूहित करने का एक बेहतर विचार नहीं है । बस एक अस्थायी, त्वरित समाधान।

जवाबों:


684

staticफ़ंक्शंस वे फ़ंक्शंस हैं जो केवल एक ही फ़ाइल में अन्य फ़ंक्शंस के लिए दिखाई देते हैं (अधिक सटीक रूप से एक ही अनुवाद इकाई )।

EDIT : उन लोगों के लिए, जिन्होंने सोचा था, सवालों के लेखक का मतलब एक 'क्लास मेथड' है: जैसा कि सवाल टैग Cकिया जाता है कि उनका मतलब एक सादे पुराने सी फ़ंक्शन से है। (C ++ / Java / ...) वर्ग विधियों के लिए, staticइसका मतलब है कि इस पद्धति को कक्षा में ही बुलाया जा सकता है, उस वर्ग का कोई उदाहरण आवश्यक नहीं है।


2
वास्तव में मैंने इसे सी ++ टैग नहीं किया था, कुछ एडिंस ने शायद किया था, लेकिन यह सी ++ के बारे में था, इसलिए सी ++ में क्या अंतर है?
स्लाव वी

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

2
नहीं, वह अभी भी C ++ फ़ंक्शन का अर्थ है। C ++ सदस्य फ़ंक्शन के बजाय C ++ मुक्त फ़ंक्शन।
कक्षा

3
@ चक: सी ++ शब्दावली कभी भी "विधि" शब्द का उपयोग नहीं करती है; यह जावा शब्दावली है - C ++ मानक दस्तावेजों में इसे हमेशा "सदस्य फ़ंक्शन" कहा जाता है ( इस उत्तर को देखें या C ++ बनाम जावा शब्दों की यह शब्दावली (जैसे C ++ "डेटा सदस्य का उपयोग करता है" और जावा "फ़ील्ड", आदि का उपयोग करता है)।
श्रीवत्सआर

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

199

C में स्थैतिक कार्यों और C ++ में स्थिर सदस्य कार्यों के बीच एक बड़ा अंतर है। सी में, एक स्थिर फ़ंक्शन इसके अनुवाद इकाई के बाहर दिखाई नहीं देता है, जो कि ऑब्जेक्ट फ़ाइल है जिसे इसमें संकलित किया गया है। दूसरे शब्दों में, एक कार्य स्थैतिक बनाने से इसका दायरा सीमित हो जाता है। आप स्टैटिक फंक्शन के बारे में सोच सकते हैं कि यह "प्राइवेट" है इसकी * .सी फाइल (हालांकि यह कड़ाई से सही नहीं है)।

सी ++ में, "स्थिर" सदस्य कार्यों और कक्षाओं के डेटा सदस्यों पर भी लागू हो सकता है। एक स्थैतिक डेटा सदस्य को "वर्ग चर" भी कहा जाता है, जबकि एक गैर-स्थैतिक डेटा सदस्य "उदाहरण चर" होता है। यह स्मालटाक शब्दावली है। इसका मतलब यह है कि किसी वर्ग के सभी ऑब्जेक्ट द्वारा साझा किए गए स्थिर डेटा सदस्य की केवल एक प्रति है, जबकि प्रत्येक ऑब्जेक्ट की एक गैर-स्थिर डेटा सदस्य की अपनी प्रतिलिपि है। तो एक स्थैतिक डेटा सदस्य अनिवार्य रूप से एक वैश्विक चर है, जो एक वर्ग का सदस्य है।

गैर-स्थैतिक सदस्य फ़ंक्शन कक्षा के सभी डेटा सदस्यों तक पहुंच सकते हैं: स्थिर और गैर-स्थिर। स्थैतिक सदस्य फ़ंक्शन केवल स्थैतिक डेटा सदस्यों पर काम कर सकते हैं।

इस बारे में सोचने का एक तरीका यह है कि C ++ में स्थैतिक डेटा सदस्य और स्थिर सदस्य फ़ंक्शन किसी ऑब्जेक्ट से संबंधित नहीं हैं, बल्कि पूरी कक्षा के लिए हैं।


42
C ++ में फ़ाइल-स्टेटिक भी है। इसमें C लाने की आवश्यकता नहीं है।
ऑर्बिट

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

3
क्या वैश्विक var और class static var (नाम स्थान को छोड़कर) में कोई अंतर है?
अलेक्जेंडर मालाखोव

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

2
क्या कोई समझा सकता है कि किसी स्थिर कार्य को अपनी .c फ़ाइल के लिए निजी रूप से कड़ाई से सही नहीं मानना क्या कहना बाकी है?
योतेंगो यूएनएलसीडी

77

जब C ++ में फ़ंक्शंस की बात आती है, तो कीवर्ड स्थिर के लिए दो उपयोग हैं।

पहला कार्य आंतरिक लिंकेज के रूप में फ़ंक्शन को चिह्नित करना है ताकि इसे अन्य अनुवाद इकाइयों में संदर्भित न किया जा सके। यह उपयोग C ++ में हटा दिया गया है। इस उपयोग के लिए getpaces को प्राथमिकता दी जाती है।

// inside some .cpp file:

static void foo();    // old "C" way of having internal linkage

// C++ way:
namespace
{
   void this_function_has_internal_linkage()
   {
      // ...
   }
}

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


1
प्रश्न c में स्थैतिक के बारे में है।
डेक्कन जूल

8
@ प्रश्न का मूल रूप से C ++ टैग किया गया था और लेखक ".cpp" फ़ाइलों का उपयोग करने के बारे में बात करता है।
ब्रायन नील

57

न्यूनतम रननीय बहु-फ़ाइल गुंजाइश उदाहरण

यहाँ मैं वर्णन करता हूँ कि कैसे static करता कई फ़ाइलों में फ़ंक्शन परिभाषाओं के दायरे को प्रभावित करता है।

एसी

#include <stdio.h>

/* Undefined behavior: already defined in main.
 * Binutils 2.24 gives an error and refuses to link.
 * /programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
 */
/*void f() { puts("a f"); }*/

/* OK: only declared, not defined. Will use the one in main. */
void f(void);

/* OK: only visible to this file. */
static void sf() { puts("a sf"); }

void a() {
    f();
    sf();
}

main.c

#include <stdio.h>

void a(void);        

void f() { puts("main f"); }

static void sf() { puts("main sf"); }

void m() {
    f();
    sf();
}

int main() {
    m();
    a();
    return 0;
}

गिटहब ऊपर

संकलित करें और चलाएं:

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
./main

आउटपुट:

main f
main sf
main f
a sf

व्याख्या

  • दो अलग-अलग कार्य हैं sf , प्रत्येक फ़ाइल के लिए एक
  • एक एकल साझा समारोह है f

हमेशा की तरह, छोटा दायरा, बेहतर, इसलिए हमेशा फ़ंक्शन घोषित करें static यदि आप कर सकते हैं।

सी प्रोग्रामिंग में, फ़ाइलों को अक्सर "कक्षाएं" का प्रतिनिधित्व करने के लिए उपयोग किया जाता है, और static फ़ंक्शन "निजी" तरीकों का प्रतिनिधित्व करते हैं।

पास करने के लिए एक सामान्य सी पैटर्न है this पहले "विधि" तर्क के रूप में संरचना , जो मूल रूप से हुड के नीचे सी ++ करता है।

इसके बारे में क्या मानक कहते हैं

C99 N1256 ड्राफ्ट 6.7.1 "स्टोरेज-क्लास स्पेसियर्स " का कहना है कि staticयह "स्टोरेज-क्लास स्पेसियर " है।

6.2.2 / 3 "पहचानकर्ताओं के लिंक" का staticअर्थ है internal linkage:

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

और 6.2.2 / 2 का कहना है कि internal linkageहमारे उदाहरण की तरह व्यवहार करता है:

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

जहाँ "अनुवाद इकाई" प्रीप्रोसेसिंग के बाद एक स्रोत फ़ाइल है।

ईएलएफ (लिनक्स) के लिए जीसीसी इसे कैसे लागू करता है?

STB_LOCALबंधन के साथ ।

यदि हम संकलित करते हैं:

int f() { return 0; }
static int sf() { return 0; }

और प्रतीक तालिका को अलग करें:

readelf -s main.o

आउटपुट में शामिल हैं:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 000000000000000b    11 FUNC    LOCAL  DEFAULT    1 sf
  9: 0000000000000000    11 FUNC    GLOBAL DEFAULT    1 f

इसलिए उनके बीच बंधन ही महत्वपूर्ण अंतर है। खंड Valueमें सिर्फ उनकी भरपाई है .bss, इसलिए हम इसे अलग करने की उम्मीद करते हैं।

STB_LOCALhttp://www.sco.com/developers/gabi/2003-12-17/ch4.syminab.html पर ELF कल्पना पर प्रलेखित है :

STB_LOCAL स्थानीय चिह्न उनकी परिभाषा वाली ऑब्जेक्ट फ़ाइल के बाहर दिखाई नहीं देते हैं। एक ही नाम के स्थानीय प्रतीक एक दूसरे के साथ हस्तक्षेप किए बिना कई फाइलों में मौजूद हो सकते हैं

जो इसका प्रतिनिधित्व करने के लिए एक आदर्श विकल्प है static

स्थिर के बिना कार्य हैं STB_GLOBAL, और युक्ति कहती है:

जब लिंक एडिटर कई रिलेक्वेसेबल ऑब्जेक्ट फ़ाइलों को जोड़ता है, तो यह एक ही नाम के साथ STB_GLOBAL प्रतीकों की कई परिभाषाओं की अनुमति नहीं देता है।

जो कई गैर स्थिर परिभाषाओं पर लिंक त्रुटियों के साथ सुसंगत है।

यदि हम अनुकूलन को क्रैंक करते हैं -O3, तो sfप्रतीक पूरी तरह से प्रतीक तालिका से हटा दिया जाता है: इसका उपयोग किसी भी तरह से बाहर से नहीं किया जा सकता है। TODO जब अनुकूलन नहीं है तो प्रतीक तालिका पर स्थिर कार्य क्यों रखें? क्या उन्हें किसी भी चीज के लिए इस्तेमाल किया जा सकता है?

यह सभी देखें

C ++ अनाम नामस्थान

C ++ में, आप स्थैतिक के बजाय अनाम नामस्थान का उपयोग करना चाह सकते हैं, जो एक समान प्रभाव प्राप्त करता है, लेकिन आगे प्रकार की परिभाषाएँ छिपाता है: / अनाम नाम स्थान बनाम स्थिर कार्य


3
नोट: void f() { puts("sf"); }(अर्थात दो परिभाषाएँ f()) अपरिभाषित व्यवहार का कारण बनता है जिसमें कोई निदान आवश्यक नहीं है। यह वास्तव में एक त्रुटि संदेश देखने के लिए एक गुणवत्ता-से-लिंकर मुद्दा है।
एमएम

2
यह सबसे अच्छा और सटीक स्पष्टीकरण है! आपके मुकाबले!
एक्वा

20

निम्नलिखित सादे सी कार्यों के बारे में है - एक सी ++ वर्ग में संशोधक 'स्थिर' का एक और अर्थ है।

यदि आपके पास सिर्फ एक फ़ाइल है, तो यह संशोधक पूरी तरह से कोई अंतर नहीं रखता है। अंतर कई फाइलों के साथ बड़ी परियोजनाओं में आता है:

सी में, प्रत्येक "मॉड्यूल" (sample.c और sample.h का एक संयोजन) स्वतंत्र रूप से संकलित किया जाता है और बाद में उन संकलित ऑब्जेक्ट फ़ाइलों (sample.o) में से प्रत्येक को लिंकर द्वारा एक निष्पादन योग्य फ़ाइल से एक साथ जोड़ा जाता है।

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

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


16

पहला: आम तौर पर किसी .cppफ़ाइल को किसी अन्य फ़ाइल में शामिल करना एक बुरा विचार है - यह इस तरह की समस्याओं की ओर जाता है :-) सामान्य तरीका अलग संकलन इकाइयाँ बनाना है, और शामिल फ़ाइल के लिए एक हेडर फ़ाइल जोड़ना है।

दूसरी बात यह है:

C ++ की यहाँ कुछ भ्रामक शब्दावली है - मुझे इस बारे में तब तक जानकारी नहीं थी जब तक कि टिप्पणियों में नहीं बताई जाती।

ए) static functions- सी से विरासत में मिला है, और आप यहां किस बारे में बात कर रहे हैं। किसी भी वर्ग के बाहर। एक स्थिर फ़ंक्शन का मतलब है कि यह वर्तमान संकलन इकाई के बाहर दिखाई नहीं देता है - इसलिए आपके मामले में a.obj की एक प्रति है और आपके अन्य कोड की एक स्वतंत्र प्रतिलिपि है। (कोड की कई प्रतियों के साथ अंतिम निष्पादन योग्य फूला हुआ)।

बी) static member function- क्या वस्तु अभिविन्यास एक स्थिर विधि है । एक वर्ग के अंदर रहता है। आप इसे ऑब्जेक्ट उदाहरण के बजाय कक्षा के साथ कहते हैं।

ये दो अलग-अलग स्थैतिक फ़ंक्शन परिभाषाएं पूरी तरह से अलग हैं। सावधान - यहाँ ड्रेगन हो।


ठीक है, मैं यह करता हूं कि कुछ जगह TEMPORARILY को main.cpp में खाली कर दें, जब तक कि मैं यह तय न कर लूं कि फाइल को उचित के साथ पुस्तकालयों में कैसे व्यवस्थित किया जाए। क्या यह करने के लिए एक बेहतर विचार है?
स्लाव वी

1
C ++ में सही शब्दावली सदस्य कार्य है, विधि नहीं। C ++ लीगल में कोई "विधियाँ" नहीं हैं। विधि एक सामान्य OO शब्द है। C ++ सदस्य कार्यों के माध्यम से उन्हें लागू करता है।
ब्रायन नील

14

स्थिर फ़ंक्शन परिभाषाएँ इस प्रतीक को आंतरिक के रूप में चिह्नित करेंगी। तो यह बाहर से लिंक करने के लिए दिखाई नहीं देगा, लेकिन केवल एक ही संकलन इकाई में कार्य करने के लिए, आमतौर पर एक ही फ़ाइल।


7

एक स्थिर कार्य वह है जिसे कक्षा में ही बुलाया जा सकता है, क्योंकि यह कक्षा की एक आवृत्ति के विपरीत है।

उदाहरण के लिए एक गैर स्थैतिक होगा:

Person* tom = new Person();
tom->setName("Tom");

यह विधि कक्षा के उदाहरण पर काम करती है, न कि कक्षा के लिए। हालाँकि आपके पास एक स्थिर विधि हो सकती है जो बिना उदाहरण के काम कर सकती है। इसे कभी-कभी फ़ैक्टरी पैटर्न में उपयोग किया जाता है:

Person* tom = Person::createNewPerson();

2
यह मुझे लगता है कि आप स्थिर "विधि" के बारे में बात कर रहे हैं, "फ़ंक्शन" नहीं?
स्लाव वी

मैंने मान लिया कि आप एक वर्ग के भीतर स्थिर कार्यों की बात कर रहे थे।
तोते

अगर मुझे C ++ में "मेथड्स" को "मेथड फंक्शन्स" कहा जाता है, तो मैं उस पर अधिक स्पष्ट रहूंगा। खैर, अब मैं करता हूँ :) वैसे भी धन्यवाद
स्लाव वी

5
सी ++ में कोई "विधियां" नहीं हैं, बस कार्य करता है। C ++ मानक कभी भी "विधियों" का उल्लेख नहीं करता है, बस "फ़ंक्शन"।
ब्रायन नील

1
@ मुझे पता है कि आप क्या कह रहे हैं लेकिन C ++ मानक में "विधि" की कोई परिभाषा नहीं है। C ++ में केवल विभिन्न प्रकार के कार्य हैं। "विधि" एक सामान्य OO शब्द है और अन्य भाषाओं में और अनौपचारिक रूप से C ++ में उपयोग किया जाता है। एक विधि को औपचारिक रूप से C ++ में "सदस्य फ़ंक्शन" के रूप में जाना जाता है।
ब्रायन नील

7

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

मानक शायद कुछ कहते हैं:

"प्रत्येक कार्यक्रम में उस प्रोग्राम में उपयोग की जाने वाली हर नॉनलाइन फ़ंक्शन या ऑब्जेक्ट की बिल्कुल एक परिभाषा होनी चाहिए; कोई निदान आवश्यक नहीं है।"

यह स्थिर कार्यों को देखने का C तरीका है। हालांकि यह C ++ में पदावनत है।

C ++ में, इसके अतिरिक्त, आप सदस्य कार्यों को स्थैतिक घोषित कर सकते हैं। ये ज्यादातर मेटाफैक्शन हैं अर्थात वे किसी विशेष वस्तु के व्यवहार / स्थिति का वर्णन / संशोधन नहीं करते हैं बल्कि पूरी कक्षा पर ही कार्य करते हैं। इसके अलावा, इसका मतलब है कि आपको स्थैतिक सदस्य फ़ंक्शन को कॉल करने के लिए ऑब्जेक्ट बनाने की आवश्यकता नहीं है। इसके अलावा, इसका मतलब यह भी है, आप केवल ऐसे फ़ंक्शन के भीतर से स्थिर सदस्य चर तक पहुँच प्राप्त कर सकते हैं।

मैं तोता के उदाहरण को सिंग्लटन पैटर्न में जोड़ दूंगा जो किसी प्रोग्राम के जीवन भर में एक ही ऑब्जेक्ट को पाने / उपयोग करने के लिए एक स्थिर सदस्य फ़ंक्शन के इस प्रकार पर आधारित है।


7

स्थैतिक कार्य का उत्तर भाषा पर निर्भर करता है:

1) सी जैसे ओओपीएस के बिना भाषाओं में, इसका मतलब है कि फ़ंक्शन केवल उस फ़ाइल के भीतर पहुंच योग्य है जहां इसकी परिभाषा है।

2) C ++ जैसी OOPS वाली भाषाओं में, इसका मतलब है कि इसका उदाहरण बनाए बिना फ़ंक्शन को सीधे कक्षा में बुलाया जा सकता है।


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

0

चूंकि स्थिर फ़ंक्शन केवल इस फ़ाइल में दिखाई देता है। वास्तव में, कंपाइलर आपके लिए कुछ ऑप्टिमाइज़ेशन कर सकता है यदि आप किसी फ़ंक्शन को "स्टैटिक" घोषित करते हैं।

ये रहा एक सरल उदाहरण।

main.c

#include <stdio.h>

static void test() 
{
    ghost(); // This is an unexist function.
}

int main()
{
    int ret = 0;

#ifdef TEST
#else
    test();
#endif
    return (ret);
} 

और संकलन करें

gcc -o main main.c

आप इसे विफल होते देखेंगे। क्योंकि आप भूत () फ़ंक्शन को भी लागू नहीं करते हैं।

लेकिन क्या होगा अगर हम निम्नलिखित कमांड का उपयोग करें।

gcc -DTEST -O2 -o main main.c

यह सफलता है , और इस कार्यक्रम को सामान्य रूप से निष्पादित किया जा सकता है।

क्यों? 3 मुख्य बिंदु हैं।

  1. -O2: संकलक अनुकूलन स्तर कम से कम 2।
  2. -डेस्ट: टेस्ट टेस्ट को परिभाषित करें, इसलिए टेस्ट () नहीं कहा जाएगा।
  3. परीक्षण के लिए परिभाषित "स्थिर" ()।

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


0

" सी में एक" static"फ़ंक्शन क्या है ? "

चलिए शुरुआत करते हैं।

यह "लिंकेज" नामक एक चीज पर आधारित है:

" एक पहचानकर्ता को अलग-अलग स्कोप में या एक ही दायरे में एक से अधिक बार घोषित किया गया है, जिसे लिंकेज नामक प्रक्रिया द्वारा एक ही वस्तु या कार्य को संदर्भित करने के लिए बनाया जा सकता है। 29) लिंकेज तीन प्रकार के होते हैं: बाहरी, आंतरिक और कोई नहीं। "

स्रोत: C18, 6.2.2 / 1


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

स्रोत: C18, 6.2.2 / 2


यदि कोई फ़ंक्शन स्टोरेज-क्लास स्पेसियर के बिना परिभाषित किया गया है, तो फ़ंक्शन के पास है extern डिफ़ॉल्ट रूप से अल लिंकेज है:

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

स्रोत: C18, 6.2.2 / 5

इसका मतलब है कि - यदि आपका प्रोग्राम कई अनुवाद इकाइयों / स्रोत फ़ाइलों ( .cया .cpp) से बना है - फ़ंक्शन में दिखाई देता है आपके प्रोग्राम के सभी अनुवाद इकाइयों / स्रोत फ़ाइलों है।

यह कुछ मामलों में एक समस्या हो सकती है। क्या होगा यदि आप फ़े दो अलग-अलग फ़ंक्शन (परिभाषाएँ) का उपयोग करना चाहते हैं, लेकिन दो अलग-अलग संदर्भों (वास्तव में फ़ाइल-संदर्भ) में एक ही फ़ंक्शन नाम के साथ।

C और C ++ में, staticस्टोरेज-क्लास क्वालिफायर फ़ाइल स्कोप पर एक फंक्शन में लागू होता है ( C ++ में किसी क्लास का स्टैटिक मेंबर फंक्शन या किसी दूसरे ब्लॉक के फंक्शन में नहीं) अब मदद के लिए आता है और यह दर्शाता है कि संबंधित फंक्शन केवल अंदर दिखाई दे रहा है अनुवाद इकाई / स्रोत फ़ाइल इसे अन्य TLUs / फ़ाइलों में परिभाषित नहीं किया गया था।

"यदि किसी ऑब्जेक्ट या किसी फ़ंक्शन के लिए फ़ाइल स्कोप आइडेंटिफ़ायर की घोषणा में स्टोरेज-क्लास स्पेसियर स्थिर है , तो पहचानकर्ता के पास आंतरिक लिंकेज है। 30)"


30) एक फ़ंक्शन घोषणा में स्टोरेज-क्लास को निर्दिष्ट किया जा सकता है यदि यह फ़ाइल दायरे में है; 6.7.1 देखें।

स्रोत: C18, 6.2.2 / 3


इस प्रकार, एक staticफ़ंक्शन केवल समझ में आता है, iff:

  1. आपका कार्यक्रम कई अनुवाद इकाइयों / स्रोत फ़ाइलों ( .cया .cpp) से बना है।

    तथा

  2. आप किसी फ़ंक्शन के दायरे को फ़ाइल में सीमित करना चाहते हैं, जिसमें विशिष्ट फ़ंक्शन परिभाषित है।

यदि ये दोनों आवश्यकताएं मेल नहीं खाती हैं, तो आपको किसी फ़ंक्शन को योग्य बनाने के बारे में अपना सिर लपेटने की आवश्यकता नहीं है static


साइड नोट्स:

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

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

    यह विभिन्न SO प्रश्नों के अधीन था:

    अनाम / अनाम नाम बनाम स्थिर कार्य

    स्थैतिक पर अनाम नामस्थान की श्रेष्ठता?

    अनाम नाम स्थान स्थैतिक का "बेहतर" विकल्प क्यों है?

    स्थैतिक खोजशब्द का पदावनति ... और नहीं?

    वास्तव में, यह अभी तक प्रति C ++ मानक के अनुसार नहीं है। इस प्रकार, staticफ़ंक्शंस का उपयोग अभी भी वैध है। भले ही अनाम नाम स्थान के फायदे हों, लेकिन C ++ में स्थिर कार्यों का उपयोग करने या न करने के बारे में चर्चा एक मन (राय-आधारित) के अधीन है और इसके साथ ही इस वेबसाइट के लिए उपयुक्त नहीं है।

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