C में "स्थिर" का क्या अर्थ है?


1135

मैंने staticसी कोड में अलग-अलग जगहों पर इस्तेमाल होने वाले शब्द को देखा है; क्या यह C # में एक स्थिर फ़ंक्शन / वर्ग की तरह है (जहाँ कार्यान्वयन वस्तुओं में साझा किया जाता है)?



15
"लंडिन" शीर्षक के अंत से "सी प्रोग्राम में" हटाने का क्या कारण है? यह टैग सी की उपस्थिति में थोड़ा बेमानी है , लेकिन यह मुझे टैग का निरीक्षण किए बिना श्रेणीकरण को अधिक तेज़ी से देखने देता है। यह अतिरेक तब बहुत सहज होता है जब मैं उस दिशा से प्रश्न पर पहुँचता हूं जिसमें अन्य भाषाओं के बारे में प्रश्न हो सकते हैं, जैसे कि स्थिर या Google खोज।
पलक

5
@Palec एक SO नीति है जो आइटम जो टैग सूची में मौजूद हैं, शीर्षक में निरर्थक हैं। साइट स्वचालित रूप से सी को वास्तविक वेब साइट पर जोड़ देगी। "सी स्टैटिक" के लिए एक Google यह उत्तर शीर्ष हिट के रूप में देता है। यह क्यों बदला गया इसका कारण यह है कि यह प्रश्न अब SO C भाषा FAQ का हिस्सा है और जो भी पोस्ट जोड़े जाते हैं वे सभी थोड़ा पॉलिश हो जाते हैं।
लुंडिन

1
@ लुंडिन मैं शीर्षक में "सी" रखना पसंद करता हूं, क्योंकि एसओ केवल एक टैग को शीर्षक (सबसे आम?) में जोड़ता है। क्या होगा अगर किसी दिन "सिंटैक्स" सी से अधिक प्रश्नों तक पहुँचता है (क्योंकि यह एक क्रॉस लैंग्वेज चीज़ है)? मैं इसके बजाय स्पष्ट व्यवहार का उपयोग करता हूं :-) संपादित करें: आह, लेकिन एक मेटा सवाल है, अन्यथा कह रहे हैं: meta.stackexchange.com/questions/19190/…
Ciro Santilli 冠状

जवाबों:


1519
  1. किसी फ़ंक्शन के अंदर एक स्थिर चर, इनवोकेशन के बीच अपना मूल्य रखता है।
  2. एक स्थिर वैश्विक चर या एक फ़ंक्शन केवल "फ़ाइल" में देखा जाता है जो इसे घोषित किया गया है

(1) यदि आप नौसिखिया हैं तो अधिक विदेशी विषय है, इसलिए यहाँ एक उदाहरण है:

#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

    printf("a = %d, sa = %d\n", a, sa);
}


int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}

यह प्रिंट:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

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

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

उद्धरण विकिपीडिया :

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

और आपके दूसरे प्रश्न का उत्तर देने के लिए, यह C # में पसंद नहीं है।

C ++ में, हालांकि, staticवर्ग विशेषताओं (एक ही कक्षा की सभी वस्तुओं के बीच साझा) और विधियों को परिभाषित करने के लिए भी उपयोग किया जाता है। C में कोई वर्ग नहीं हैं, इसलिए यह सुविधा अप्रासंगिक है।


179
पैक्स, ओपी को स्थैतिक के बारे में पता नहीं है, इसलिए आप उसे संकलन इकाइयों और फाइलों के बीच के अंतर में डुबाने का सुझाव देते हैं? :-)
एली बेंडरस्की

138
एक संकलन इकाई एक फ़ाइल है जो कंपाइलर देखता है। आपकी .c फाइल में अन्य .c फाइलें शामिल हो सकती हैं, लेकिन प्रीप्रोसेसर में शामिल सॉर्ट करने के बाद, कंपाइलर अंततः एक एकल "संकलन इकाई" देखता है।
एली बेंडरस्की

81
@robUK: संकलक को .h फ़ाइलों के बारे में भी पता नहीं है - ये प्री-प्रोसेसर में .c फ़ाइलों में संयुक्त हैं। तो हाँ आप कह सकते हैं कि .c फ़ाइल, जिसमें सभी हेडर शामिल हैं, एक एकल संकलन इकाई हैं।
एली बेंडरस्की

6
@ टोनी शायद यह भ्रमित कर रहा है, लेकिन यह है कि संकलन कैसे काम करता है। यह आमतौर पर .cहेडर फ़ाइलों में से एक और गुच्छा हो सकता है , लेकिन शैतान हमेशा वही होता है जो विशिष्ट नहीं है
12

7
@TonyD संकलक संकलन करता है। प्रीप्रोसेसर प्रीप्रोसेसिंग करता है। टूलकिन को 'कंपाइलर' कहने से यह नहीं बदलता कि यह क्या है या यह क्या करता है।
माइल राउत

231

एक और उपयोग है जिसे यहां कवर नहीं किया गया है, और यह एक फ़ंक्शन के तर्क के रूप में एक सरणी प्रकार की घोषणा के भाग के रूप में है:

int someFunction(char arg[static 10])
{
    ...
}

इस संदर्भ में, यह निर्दिष्ट करता है कि इस फ़ंक्शन के लिए दिए गए तर्क charमें कम से कम 10 तत्वों के साथ एक प्रकार का एक सरणी होना चाहिए । अधिक जानकारी के लिए मेरा प्रश्न यहाँ देखें ।


3
मुझे नहीं लगता कि सी में सरणी तर्क थे? लिनुस टोरवाल्ड्स ऐसा करने वाले लोगों के बारे में गुस्से में चिल्लाते हैं।
सुपरजामी

13
@jamieb: सी सरणी तर्क नहीं है, लेकिन इस विशिष्ट वाक्यविन्यास का मतलब है कि समारोह की उम्मीद arg[0]करने के लिए के माध्यम से arg[9]मूल्यों के लिए (जो भी मतलब है कि समारोह एक अशक्त सूचक को स्वीकार नहीं करता)। कंपाइलर इस जानकारी को अनुकूलन के लिए किसी भी तरह से उपयोग कर सकते हैं, और स्थैतिक विश्लेषक इस जानकारी का उपयोग यह सुनिश्चित करने के लिए कर सकते हैं कि फ़ंक्शन को कभी भी शून्य सूचक नहीं दिया गया है (या यदि यह बता सकता है, तो निर्दिष्ट की तुलना में कम तत्वों वाला एक सरणी)।
ड्रीमलैक्स

19
@Qix - यह staticC99 में दिया गया एक नया अतिभारित अर्थ था । यह डेढ़ दशक से अधिक पुराना है, लेकिन सभी संकलक लेखकों ने C99 की सभी विशेषताओं को नहीं अपनाया है - इसलिए C99 पूरी तरह से अज्ञात है।
हैप्पी ग्रीन किड नप्स

@suprjami मुझे 100% यकीन नहीं है कि आप "सरणी तर्क" से क्या मतलब है , लेकिन अगर आप मतलब है int arr[n];, तो वह एक VLA (चर-लंबाई सरणी) है , जिसे C99 में जोड़ा गया था। क्या आपका आशय यही था?
रस्तजेडी

170

संक्षिप्त उत्तर ... यह निर्भर करता है।

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

  2. वे जिस फ़ाइल में परिभाषित किए गए हैं, उसके बाहर स्थैतिक वैश्विक चर दिखाई नहीं देते हैं।

  3. वे जिस फ़ाइल में परिभाषित हैं, उसके बाहर स्टेटिक फ़ंक्शंस दिखाई नहीं देते हैं।


8
तो क्या "स्टैटिक फंक्शन" और "प्राइवेट फंक्शन" का मतलब एक ही है? इसी तरह "स्थिर वैश्विक चर" और "निजी वैश्विक चर" एक ही बात हैं?
user1599964

40
यह सी के बारे में है। सी। में कोई निजी / सार्वजनिक नहीं है
क्रिस

19
@ user1599964 हालांकि privateसी में नहीं है, आपका सादृश्य अच्छा है: स्थैतिक किसी दिए गए फ़ाइल को "निजी" बनाता है। और सी में फाइलें अक्सर सी ++ में कक्षाओं के लिए मैप करती हैं।
सिरो सेंटिल्ली 冠状 病毒 i i ''

66

बहु-फ़ाइल चर गुंजाइश उदाहरण

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

एसी

#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
*/
/*int i = 0;*/

/* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 */
/*int i;*/

/* OK: extern. Will use the one in main. */
extern int i;

/* OK: only visible to this file. */
static int si = 0;

void a() {
    i++;
    si++;
    puts("a()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

main.c

#include <stdio.h>

int i = 0;
static int si = 0;

void a();    

void m() {
    i++;
    si++;
    puts("m()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

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

गिटहब ऊपर

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

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

आउटपुट:

m()
i = 1
si = 1

m()
i = 2
si = 2

a()
i = 3
si = 1

a()
i = 4
si = 2

व्याख्या

  • दो भिन्न चर हैं si, प्रत्येक फ़ाइल के लिए एक
  • के लिए एक एकल साझा चर है i

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

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

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

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

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

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

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

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

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

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

STB_LOCALबंधन के साथ ।

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

int i = 0;
static int si = 0;

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

readelf -s main.o

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

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 si
 10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 i

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

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

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

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

स्थैतिक के बिना चर हैं STB_GLOBAL, और कल्पना कहती है:

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

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

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

यह सभी देखें

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

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


39

निर्भर करता है:

int foo()
{
   static int x;
   return ++x;
}

फ़ंक्शन 1, 2, 3, आदि वापस आ जाएगा --- चर स्टैक पर नहीं है।

एसी:

static int foo()
{
}

इसका मतलब है कि इस फ़ंक्शन में केवल इस फ़ाइल में गुंजाइश है। तो ac और bc में अलग-अलग foo()s हो सकते हैं , और foo साझा ऑब्जेक्ट के संपर्क में नहीं आते हैं। इसलिए यदि आप एसी में फू को परिभाषित करते हैं तो आप इसे b.cकिसी अन्य स्थान से या उससे एक्सेस नहीं कर सकते हैं।

अधिकांश सी पुस्तकालयों में सभी "निजी" कार्य स्थिर हैं और अधिकांश "सार्वजनिक" नहीं हैं।


18
स्टैक या हीप पर x का उल्लेख करने के लिए +1। यह स्टैटिक मेमोरी स्पेस पर है।
Gob00st 11

1
@ Gob00st स्थिर मेमोरी स्पेस? आपका मतलब "डेटा सेगमेंट" था ...?
युषा अलायबौ

24

लोग कहते रहते हैं कि C में 'स्थिर' के दो अर्थ हैं। मैं इसे देखने का एक वैकल्पिक तरीका प्रदान करता हूं जो इसे एक ही अर्थ देता है:

  • उस आइटम पर 'स्थिर' को लागू करना जो उस आइटम को दो गुण रखने के लिए मजबूर करता है: (ए) यह वर्तमान दायरे के बाहर दिखाई नहीं देता है; (b) यह लगातार है।

ऐसा लगता है कि दो अर्थ होने का कारण यह है कि, C में, प्रत्येक आइटम जिस पर 'स्थिर' लागू किया जा सकता है , इन दोनों गुणों में से एक है , इसलिए ऐसा लगता है जैसे कि उस विशेष उपयोग में केवल अन्य शामिल हैं।

उदाहरण के लिए, चर पर विचार करें। फ़ंक्शंस के बाहर घोषित चर (डेटा सेगमेंट में) पहले से ही दृढ़ता रखते हैं, इसलिए 'स्थैतिक' को लागू करने से उन्हें केवल वर्तमान क्षेत्र (संकलन इकाई) के बाहर दिखाई नहीं दे सकता है। कंट्राइवाइज, फ़ंक्शंस के अंदर घोषित किए गए वैरिएबल में पहले से ही मौजूदा स्कोप (फंक्शन) के बाहर नॉन-विजिबिलिटी होती है, इसलिए 'स्टैटिक' को लागू करना केवल उन्हें लगातार बना सकता है।

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

नोट: ये टिप्पणियां केवल C ++ में C ++ पर लागू होती हैं, 'स्टेटिक' को क्लास के तरीकों पर लागू करना सही मायने में कीवर्ड को एक अलग अर्थ देता है। इसी तरह C99 सरणी-तर्क एक्सटेंशन के लिए।


आपका (क) सबसे अच्छा बेमानी है। कोई भी चर इसके दायरे से बाहर दिखाई नहीं देता है। यह बस गुंजाइश की परिभाषा है। आपके मतलब के सी स्टैंडर्ड में लिंकेज कहा जाता है। एक पहचानकर्ता को आंतरिक संबंधstatic देता है ।
जेन्स

16

विकिपीडिया से:

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


16

static अलग-अलग संदर्भों में अलग-अलग चीजों का मतलब है।

  1. आप एक सी फ़ंक्शन में एक स्थिर चर घोषित कर सकते हैं। यह चर केवल फ़ंक्शन में दिखाई देता है, हालांकि यह एक वैश्विक की तरह व्यवहार करता है कि यह केवल एक बार आरंभिक है और यह इसके मूल्य को बरकरार रखता है। इस उदाहरण में, हर बार जब आप कॉल foo()करते हैं तो यह बढ़ती संख्या को प्रिंट करेगा। स्थिर चर केवल एक बार शुरू होता है।

    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
  2. स्थैतिक का एक और उपयोग तब होता है जब आप एक .c फ़ाइल में किसी फ़ंक्शन या वैश्विक चर को लागू करते हैं, लेकिन यह नहीं चाहते कि उसका प्रतीक .objफ़ाइल द्वारा उत्पन्न के बाहर दिखाई दे । जैसे

    static void foo() { ... }

8

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

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


8

मैं एक पुराने सवाल का जवाब देने से नफरत करता हूं, लेकिन मुझे नहीं लगता कि किसी ने भी उल्लेख किया है कि कैसे और आर ने इसे "द सी प्रोग्रामर लैंग्वेज" के सेक्शन A4.1 में समझाया।

संक्षेप में, स्थैतिक शब्द का प्रयोग दो अर्थों के साथ किया जाता है :

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

पीटर वान डेर लिंडेन "विशेषज्ञ सी प्रोग्रामिंग" में ये दो अर्थ देते हैं:

  • किसी फ़ंक्शन के अंदर, कॉल के बीच इसके मूल्य को बरकरार रखता है।
  • फ़ंक्शन स्तर पर, केवल इस फ़ाइल में दिखाई देता है।

एक तीसरा भंडारण वर्ग है, रजिस्टर करें । कुछ लोगों को भी एक चौथाई भंडारण वर्ग के लिए मामला बनाने, आवंटित , भंडारण के लिए malloc और दोस्तों से लौट आए।
जेन्स

@ जैन 'रजिस्टर' केवल संकलक के लिए एक संकेत है; सी स्रोत के भीतर से रजिस्टर स्टोरेज को लागू नहीं किया जा सकता है। इसलिए मैं इसे भंडारण वर्ग नहीं मानूंगा।
जर्मनरेड

1
@GermanNerd मैं अपने दृश्य के साथ डर लग रहा है आईएसओ सी स्टैंडर्ड असहमत, के रूप में यह स्पष्ट रूप से बनाता है registerएक भंडारण-वर्ग विनिर्देशन (C99 6.7.1 भंडारण स्तरीय विनिर्देशक)। और यह सिर्फ एक संकेत से अधिक है, उदाहरण के लिए आप &संचयक के साथ ऑब्जेक्ट पर ऑपरेटर के पते को लागू नहीं कर सकते हैं register, चाहे कंपाइलर एक रजिस्टर आवंटित करता है या नहीं।
जेन्स

@ जेन्स मुझे और के बारे में याद दिलाने के लिए धन्यवाद। मैंने बहुत ज्यादा C ++ ..... किसी भी तरह से किया हो सकता है, जबकि 'रजिस्टर' एक स्टोरेज-क्लास स्पेसियर है, वास्तव में कंपाइलर 'बेकार' 'ऑटो' स्पेसियर के लिए 'रजिस्टर' के समान मशीन कोड बनाएगा। 'निर्दिष्ट करनेवाला। तो केवल एक चीज शेष है जो स्रोत-कोड स्तर का प्रतिबंध है जो पते लेने में सक्षम नहीं है। BTW, इस छोटी सी चर्चा ने मुझे नेटबीन्स में एक बग खोजने के लिए प्रेरित किया; मेरे नवीनतम अपडेट के बाद से, यह नए C प्रोजेक्ट्स पर g ++ टूल चेन के लिए डिफॉल्ट करता है!
जर्मनअर्ड

6

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

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

void procedure(void)
{
   static int i = 0;

   i++;
}

'i' का मान प्रक्रिया के पहले कॉल पर शून्य से आरंभ किया जाता है, और प्रक्रिया को बाद में हर बार मान को बनाए रखा जाता है। अगर 'i' प्रिंट होता है तो यह 0, 1, 2, 3, के अनुक्रम का उत्पादन करेगा ...


5

यह ध्यान रखना महत्वपूर्ण है कि फ़ंक्शन में स्थिर चर उस फ़ंक्शन में पहली प्रविष्टि पर आरंभीकृत हो जाते हैं और उनकी कॉल समाप्त होने के बाद भी बने रहते हैं; पुनरावर्ती कार्यों के मामले में स्टेटिक वैरिएबल केवल एक बार आरंभिक हो जाता है और सभी पुनरावर्ती कॉलों के साथ-साथ फ़ंक्शन की कॉल समाप्त होने के बाद भी बना रहता है।

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


5

यदि आप इसे एक mytest.cफ़ाइल में घोषित करते हैं :

static int my_variable;

तब यह चर केवल इस फ़ाइल से देखा जा सकता है। चर को कहीं और निर्यात नहीं किया जा सकता है।

यदि आप किसी फ़ंक्शन के अंदर घोषित करते हैं, तो प्रत्येक बार फ़ंक्शन को बुलाया जाने पर चर का मूल्य अपना मूल्य रखेगा।

किसी स्थिर फ़ंक्शन को फ़ाइल के बाहर से निर्यात नहीं किया जा सकता है। तो एक *.cफ़ाइल में, आप फ़ंक्शन और चर को छिपा रहे हैं यदि आप उन्हें स्थिर घोषित करते हैं।


4

सी में स्थैतिक चर कार्यक्रम का जीवनकाल है।

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

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

void function()
{
    static int var = 1;
    var++;
    printf("%d", var);
}

int main()
{
    function(); // Call 1
    function(); // Call 2
}

उपरोक्त कार्यक्रम varमें, डेटा खंड में संग्रहीत किया जाता है। इसका जीवनकाल संपूर्ण C कार्यक्रम है।

फ़ंक्शन कॉल 1 के बाद, var2 हो जाता है। फ़ंक्शन कॉल 2 के बाद, var3 हो जाता है।

varफ़ंक्शन कॉल के बीच का मान नष्ट नहीं होता है।

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

प्रारंभिक स्थिर वैरिएबल C प्रोग्राम के डेटा सेगमेंट में संग्रहीत किए जाते हैं, जबकि असंगठित बीएसएस सेगमेंट में संग्रहीत किए जाते हैं।

स्टैटिक के बारे में एक और जानकारी: यदि कोई वैरिएबल ग्लोबल और स्टैटिक है, तो उसके पास C प्रोग्राम का लाइफ टाइम है, लेकिन इसमें फाइल स्कोप है। यह केवल उस फ़ाइल में दिखाई देता है।

इसे आज़माने के लिए:

file1.c

static int x;

int main()
{
    printf("Accessing in same file%d", x):
}

file2.c

    extern int x;
    func()
    {
        printf("accessing in different file %d",x); // Not allowed, x has the file scope of file1.c
    }

run gcc -c file1.c

gcc -c file2.c

अब उनका उपयोग करके लिंक करने का प्रयास करें:

gcc -o output file1.o file2.o

यह एक लिंकर त्रुटि देगा क्योंकि x में file1.c की फाइल गुंजाइश है और लिंकर फाइल 2.c में प्रयुक्त चर x के संदर्भ को हल करने में सक्षम नहीं होगा।

संदर्भ:

  1. http://en.wikipedia.org/wiki/Translation_unit_(programming)
  2. http://en.wikipedia.org/wiki/Call_stack

मैं समझता हूं कि डेटा लगातार बना रहता है, जिसका अर्थ है कि यह प्रत्येक फ़ंक्शन कॉल के बाद खो नहीं जाएगा, लेकिन static int var = 1;हर बार एक मान को वापस क्यों नहीं बदलता
Eames

3

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

void func(){
    static int count; // If you don't declare its value, the value automatically initializes to zero
    printf("%d, ", count);
    ++count;
}

void main(){
    while(true){
        func();
    }
}

उत्पादन:

0, 1, 2, 3, 4, 5, ...


आप printf("%d, ", count); count++;`प्रिंटफ़ ("% d, ", गणना ++) (ऐसा नहीं है कि यह मायने रखता है: पी) के साथ बदल सकते हैं।
रस्तजेडी

2

एक स्थिर चर मान अलग-अलग फ़ंक्शन कॉल के बीच बनी रहती है और यह स्कोप स्थानीय ब्लॉक तक सीमित होता है, एक स्थिर संस्करण हमेशा मान 0 के साथ आरंभ होता है


2

2 मामले हैं:

(1) स्थानीय चर घोषित static: स्टैक के बजाय डेटा खंड में आवंटित। जब आप फ़ंक्शन को दोबारा कॉल करते हैं तो इसका मान बरकरार रहता है।

(2) वैश्विक चर या फ़ंक्शन घोषित static: अदृश्य बाहर संकलन इकाई (यानी लिंकिंग के दौरान प्रतीक तालिका में स्थानीय प्रतीक हैं)।


1

स्थैतिक चर के पास अपने दायरे से बाहर होने के बाद भी उनके मूल्य को संरक्षित करने की संपत्ति होती है ! इसलिए, स्थैतिक चर अपने पिछले मान में अपने पिछले मूल्य को संरक्षित करते हैं और नए दायरे में फिर से आरंभ नहीं होते हैं।

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

#include<stdio.h> 
int fun() 
{ 
  static int count = 0; 
  count++; 
  return count; 
} 

int main() 
{ 
  printf("%d ", fun()); 
  printf("%d ", fun()); 
  return 0; 
}

यह आउटपुट होगा: 1 2

1 के रूप में स्मृति में रहता है क्योंकि यह स्थिर घोषित किया गया था

स्टेटिक चर (जैसे वैश्विक चर) को 0 के रूप में आरंभीकृत किया जाता है यदि स्पष्ट रूप से प्रारंभ नहीं किया जाता है। नीचे दिए गए कार्यक्रम में उदाहरण के लिए, x का मान 0 के रूप में मुद्रित किया जाता है, जबकि y का मूल्य कुछ कचरा है। अधिक जानकारी के लिए इसे देखें।

#include <stdio.h> 
int main() 
{ 
    static int x; 
    int y; 
    printf("%d \n %d", x, y); 
}

यह आउटपुट होगा: 0 [some_garbage_value]

ये प्रमुख हैं जो मैंने पाया कि ऊपर एक नौसिखिया के लिए समझाया नहीं गया था!


-1

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

#include<stdio.h> 
int counterFunction() 
{ 
  static int count = 0; 
  count++; 
  return count; 
} 

int main() 
{ 
  printf("First Counter Output = %d\n", counterFunction()); 
  printf("Second Counter Output = %d ", counterFunction()); 
  return 0; 
}

उपरोक्त कार्यक्रम हमें यह आउटपुट देगा:

First Counter Output = 1 
Second Counter Output = 1 

क्योंकि जैसे ही हम फ़ंक्शन को कॉल करते हैं, यह इनिशियलाइज़ करेगा count = 0। और जब हम counterFunctionइसे निष्पादित करते हैं तो यह गिनती चर को नष्ट कर देगा।


2
> उपरोक्त कार्यक्रम हमें यह आउटपुट देगा: पहला काउंटर आउटपुट = 1 दूसरा काउंटर आउटपुट = 1 <सत्य नहीं। स्टेटिक वैरिएबल केवल एक बार आरंभिक हो जाते हैं। तो आउटपुट 1 होगा, फिर 2, और इसी तरह।
जर्मनरेड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.