C में फ़ंक्शन को स्थिर बनाने का क्या मतलब है?
C में फ़ंक्शन को स्थिर बनाने का क्या मतलब है?
जवाबों:
एक समारोह बनाना static
अन्य अनुवाद इकाइयों से खाल यह है, जो मदद करता है प्रदान करते हैं कैप्सूलीकरण ।
helper_file.c
int f1(int); /* prototype */
static int f2(int); /* prototype */
int f1(int foo) {
return f2(foo); /* ok, f2 is in the same translation unit */
/* (basically same .c file) as f1 */
}
int f2(int foo) {
return 42 + foo;
}
main.c :
int f1(int); /* prototype */
int f2(int); /* prototype */
int main(void) {
f1(10); /* ok, f1 is visible to the linker */
f2(12); /* nope, f2 is not visible to the linker */
return 0;
}
#include <helper_file.c>
? मुझे लगता है कि यह तब एक एकल अनुवाद इकाई बना देगा ...
gcc -std=c99 -pedantic -Wall -Wextra main.c helper_file.c
। फ़ंक्शंस के प्रोटोटाइप दोनों स्रोत फ़ाइलों (हेडर फ़ाइलों की कोई आवश्यकता नहीं) में मौजूद हैं। लिंकर कार्यों को हल करेगा।
pmg encapsulation के बारे में हाजिर है; अन्य अनुवाद इकाइयों (या बल्कि, इसकी वजह से) से फ़ंक्शन को छुपाने से परे , कार्य करनाstatic
से कंपाइलर अनुकूलन की उपस्थिति में प्रदर्शन लाभ भी मिल सकता है।
क्योंकि एक static
फ़ंक्शन को वर्तमान अनुवाद इकाई के बाहर कहीं से नहीं बुलाया जा सकता है (जब तक कि कोड अपने पते पर एक संकेतक नहीं लेता है), संकलक इसमें सभी कॉल बिंदुओं को नियंत्रित करता है।
इसका मतलब यह है कि यह एक गैर-मानक एबीआई का उपयोग करने के लिए स्वतंत्र है, इसे पूरी तरह से इनलाइन करें, या किसी भी अन्य अनुकूलन के किसी भी संख्या को निष्पादित करें जो बाहरी लिंकेज के साथ फ़ंक्शन के लिए संभव नहीं हो सकता है।
static
फ़ंक्शन का सूचक वर्तमान अनुवाद इकाई से बच जाता है, तो उस फ़ंक्शन को सीधे अन्य अनुवाद इकाइयों से कॉल किया जा सकता है।
static
सी में कीवर्ड एक संकलित फ़ाइल (ग के रूप में ज के खिलाफ) तो समारोह केवल उस फ़ाइल में मौजूद है में प्रयोग किया जाता है।
आम तौर पर, जब आप एक फंक्शन बनाते हैं, तो कंपाइलर cruft जेनरेट करता है, लिंकर उस फंक्शन के लिए फंक्शन कॉल लिंक कर सकता है। यदि आप स्थैतिक कीवर्ड का उपयोग करते हैं, तो उसी फ़ाइल के भीतर अन्य फ़ंक्शन इस फ़ंक्शन को कॉल कर सकते हैं (क्योंकि यह लिंकर का सहारा लिए बिना किया जा सकता है), जबकि लिंकर के पास अन्य फ़ाइलों को फ़ंक्शन तक पहुंचने की कोई जानकारी नहीं है।
ऊपर के पदों को देखते हुए मैं एक बात और बताना चाहूंगा।
मान लीजिए कि हमारी मुख्य फ़ाइल ("main.c") इस तरह दिखती है:
#include "header.h"
int main(void) {
FunctionInHeader();
}
अब तीन मामलों पर विचार करें:
केस 1: हमारी हेडर फाइल ("हैडर.एच") इस तरह दिखाई देती है:
#include <stdio.h>
static void FunctionInHeader();
void FunctionInHeader() {
printf("Calling function inside header\n");
}
फिर linux पर निम्न कमांड:
gcc main.c header.h -o main
सफल होंगे ! इसके बाद अगर कोई चलता है
./main
आउटपुट होगा
हेडर के अंदर कॉलिंग फंक्शन
वह कौन सा है जो स्थिर फ़ंक्शन को प्रिंट करना चाहिए।
केस 2: हमारी हेडर फाइल ("हैडर.एच") इस तरह दिखती है:
static void FunctionInHeader();
और हमारे पास एक और फ़ाइल "शीर्ष लेख" है, जो इस तरह दिखता है:
#include <stdio.h>
#include "header.h"
void FunctionInHeader() {
printf("Calling function inside header\n");
}
फिर निम्नलिखित कमांड
gcc main.c header.h header.c -o main
कोई त्रुटि देगा।
केस 3:
केस 2 के समान, सिवाय इसके कि अब हमारी हेडर फाइल ("हैडर.एच") है:
void FunctionInHeader(); // keyword static removed
फिर 2 आदेश के रूप में एक ही आदेश सफल होगा, और आगे क्रियान्वयन ./main अपेक्षित परिणाम देगा।
तो इन परीक्षणों (एसर x86 मशीन, उबंटू ओएस पर निष्पादित) से मैंने एक धारणा बनाई
स्थिर कीवर्ड फ़ंक्शन को किसी अन्य * .c फ़ाइल में कहा जाता है, जहां इसे परिभाषित किया गया है, रोकता है।
अगर मैं ग़लत हूं तो मेरी गलती सुझाएं।
C प्रोग्रामर मॉड्यूल के अंदर चर और फ़ंक्शन घोषणाओं को छिपाने के लिए स्थिर विशेषता का उपयोग करते हैं, जितना कि आप जावा और C ++ में सार्वजनिक और निजी घोषणाओं का उपयोग करेंगे। सी स्रोत फ़ाइलें मॉड्यूल की भूमिका निभाती हैं। स्थैतिक विशेषता के साथ घोषित कोई भी वैश्विक चर या फ़ंक्शन उस मॉड्यूल के लिए निजी है। इसी तरह, स्थिर विशेषता के बिना घोषित कोई भी वैश्विक चर या फ़ंक्शन सार्वजनिक है और किसी अन्य मॉड्यूल द्वारा एक्सेस किया जा सकता है। जहाँ भी संभव हो, स्थैतिक विशेषता के साथ अपने चर और कार्यों की रक्षा करना अच्छा प्रोग्रामिंग अभ्यास है।
pmg का जवाब बहुत ही ठोस है। यदि आप जानना चाहते हैं कि वस्तु स्तर पर स्थैतिक घोषणाएँ कैसे काम करती हैं, तो यह नीचे दी गई जानकारी आपके लिए दिलचस्प हो सकती है। मैंने pmg द्वारा लिखे गए उसी कार्यक्रम का पुन: उपयोग किया और इसे .so (साझा ऑब्जेक्ट) फ़ाइल में संकलित किया
निम्नलिखित सामग्री कुछ मानव पठनीय में .so फ़ाइल को डंप करने के बाद हैं
0000000000000675 f1 : f1 फ़ंक्शन का पता
000000000000068c f2 : f2 (स्टेटिक) फ़ंक्शन का पता
फ़ंक्शन पते में अंतर पर ध्यान दें, इसका मतलब कुछ है। एक फ़ंक्शन के लिए जिसे अलग-अलग पते के साथ घोषित किया गया है, यह बहुत अच्छी तरह से संकेत दे सकता है कि एफ 2 बहुत दूर या ऑब्जेक्ट फ़ाइल के एक अलग सेगमेंट में रहता है।
लिंकर्स PLT (प्रोसीजर लिंकेज टेबल) और GOT (ग्लोबल ऑफसेट टेबल) नामक कुछ चीज़ों का इस्तेमाल करते हैं ताकि वे उन प्रतीकों को समझ सकें जिनसे उन्हें लिंक करने की पहुंच है।
अब के लिए सोचते हैं कि GOT और PLT जादुई रूप से सभी पतों को बांधते हैं और एक गतिशील अनुभाग इन सभी कार्यों की जानकारी रखता है जो लिंकर द्वारा दिखाई देते हैं।
.So फ़ाइल के डायनामिक सेक्शन को डंप करने के बाद हमें प्रविष्टियों का एक गुच्छा मिलता है लेकिन केवल f1 और f2 फ़ंक्शन में रुचि होती है।
डायनामिक सेक्शन में केवल f1 फ़ंक्शन के लिए पता 0000000000000675 है और f2 के लिए प्रविष्टि है !
संख्या: मान का आकार प्रकार बाइंड विज़ निडक्स नाम
9: 0000000000000675 23 FUNC GLOBAL DEFAULT 11 f1
और बस !। इस से यह स्पष्ट है कि लिंकर f2 फंक्शन को खोजने में असफल रहेगा क्योंकि यह इनसो फाइल के डायनामिक सेक्शन में नहीं है।
जब कुछ कार्यों तक पहुँच को प्रतिबंधित करने की आवश्यकता होती है, तो हम फ़ंक्शन को परिभाषित और घोषित करते समय स्थैतिक कीवर्ड का उपयोग करेंगे।
/* file ab.c */
static void function1(void)
{
puts("function1 called");
}
And store the following code in another file ab1.c
/* file ab1.c */
int main(void)
{
function1();
getchar();
return 0;
}
/* in this code, we'll get a "Undefined reference to function1".Because function 1 is declared static in file ab.c and can't be used in ab1.c */