सी

2010-04-09 9 views
16

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

#include <stdio.h> 

static double m = 30000; 

int main(void) 
{ 
value = m * 2 + 3; 
} 

यहां परिवर्तनीय एम का निरंतर मूल्य है जो मुख्य कार्यक्रम में बाद में संशोधित नहीं होगा।

const double m = 30000; 

या

#define m 30000 //m or M 

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

+0

दिलचस्प उत्तरों के लिए सभी को धन्यवाद। तो मुझे लगता है कि मेरे मामले में सबसे अच्छी चीज स्थिर कॉन्स डबल = 30000 है। – yCalleecharan

उत्तर

12
static double m = 30000; 

double foo(double x, double y) { 
    return x/m + y; 
} 

यह आपको कुछ भी नहीं जीतता है। गणना करने के लिए एम की एक प्रति बनाना है। इसके अलावा, अगर आप ऐसा करेंगे:

double bar(double x, double y) { 
    m += x + y; 
    return m; 
} 

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

फ़ंक्शन के अंदर स्थिर चर अभी भी वैश्विक चर की तरह हैं, सिवाय इसके कि एक ही फ़ाइल में अन्य फ़ंक्शंस उन्हें सीधे नहीं देख सकते हैं।

const double m = 30000; 

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

नीचे की तरफ यह है कि संकलक को यह मानना ​​है कि अन्य सॉस फ़ाइलें एम को पढ़ना चाहती हैं और वास्तव में ऑब्जेक्ट फ़ाइल में एक प्रतिलिपि (लेकिन स्थिर चर) के रूप में एक प्रतिलिपि को स्टोर करना पड़ता है।

मुझे यकीन नहीं है कि यह मानक है लेकिन आप कभी-कभी extern const double m = 30000; कर सकते हैं और संकलक 30000 का उपयोग ऑप्टिमाइज़ करने के लिए करेंगे और मान लें कि एक और फ़ाइल में वास्तव में एम की प्रति है जो निष्पादन योग्य में संग्रहीत की जाएगी। आप static const double m = 30000; भी कर सकते हैं और संकलक यह मान सकता है कि कोई भी उम्मीद नहीं करेगा कि एम की एक प्रति इस स्रोत फ़ाइल से उत्पन्न ऑब्जेक्ट कोड में संग्रहीत की जाती है।

#define m 30000 

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

#define BASE_ADDRESS 48 
#define MY_OFFSET 9 
#define MY_ADDRESS BASE_ADDRESS+MY_OFFSET 
... 
    return MY_ADDRESS*4; 

हाँ, यह एक बेवकूफ उदाहरण है, लेकिन क्या इस के बाद पूर्वप्रक्रमक यह के साथ किया जाता है की तरह लग रहा

... 
    return 48+9*4; 

कौन सा

return 48+(9*4); 

और वह है है जो आप शायद चाहते थे नहीं।

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

#define JIM "Jim" 
#define JOHN "John" 

और फिर सभी अपने कार्यक्रमों के ऊपर जिम और जॉन का इस्तेमाल किया: आप आसानी से एक बहुत बड़े कार्यक्रम बना सकता है अगर आप की तरह सामान की बहुत सारी था जोम "और" जॉन "कार्यक्रम में एक बार।

ऐसा कहा जा रहा है कि स्थिरांक को इस तरह घोषित करने के लिए असामान्य नहीं है, और अक्सर वे लोग जो जानते हैं कि वे क्या कर रहे हैं, ठीक से ऐसा किया जाता है।

+0

लंबी व्याख्या के लिए धन्यवाद। तो अगर मेरे पास एक ही फाइल में सभी कोड हैं, तो स्थिर कॉन्स डबल एम = 30000 मुझे लगता है कि सबसे अच्छा जवाब है। – yCalleecharan

+0

सभी कंपाइलर दो स्ट्रिंग अक्षरों को समान मानेंगे और उन्हें केवल एक बार स्टोर करेंगे। – Tomas

+0

कुछ मामलों में आपको 'const' के बजाय 'परिभाषित' के साथ करना होगा। 'स्थिर कॉन्स uint8_t ARRAY_SIZE = 16U; uint8_t सरणी [ARRAY_SIZE] 'काम नहीं करती है क्योंकि' ARRAY_SIZE' स्पष्ट निरंतर मान नहीं है। 'Const uint8_t SECONDS_PER_MINUTE = 60U के साथ ही; const uint16_t SECONDS_PER_HOUR = 60U * SECONDS_PER_MINUTE; ', यह काम नहीं करता है। जो एक बड़ी बड़ी शर्म की बात है। – Gauthier

5

static किसी फ़ंक्शन के बाहर घोषित ऑब्जेक्ट के लिए केवल ऑब्जेक्ट स्थानीय को अनुवाद इकाई में बनाता है (यानी इसे अन्य .c फ़ाइलों से एक्सेस नहीं किया जा सकता है)। यह इसे स्थिर नहीं बनाता है। यह const था। वे ऑर्थोगोनल हैं ताकि आप एक या दूसरे या दोनों हो सकें।

उदा।

static const double m = 5; 

#define एक मैक्रो जो (इस मामले में) एक निरंतर मूल्य के रूप में इस्तेमाल किया जा सकता की घोषणा की। कोई ऑब्जेक्ट नहीं है, इसलिए const लागू नहीं होता है क्योंकि ऑब्जेक्ट को बदला नहीं जा सकता है। नतीजतन, आप एक मैक्रो का पता भी नहीं ले सकते हैं।

+0

बस थोड़ा जोड़ने के लिए: 'const' और 'static' सी ++ में ऑर्थोगोनल के रूप में काफी नहीं हैं क्योंकि वे सी ++ में हैं, एक फ़ंक्शन के बाहर परिभाषित एक' const' चर डिफ़ॉल्ट रूप से 'स्थिर' भी है। –

+0

@ जेरी: निश्चित रूप से, लेकिन यह एक सी प्रश्न और एक शुरुआती सवाल है, इसलिए शायद यह एक विवरण है जो उत्तर को जटिल बनाने के लायक नहीं है। –

+0

क्या ऑर्थोगोनल सही शब्द है? या आप पारस्परिक मतलब था? जैसा कि आपने कहा था कि हम या तो एक या दूसरे या दोनों कर सकते हैं। – yCalleecharan

7

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

1

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

const और #define का उपयोग करने के बीच अंतर यह है कि पूर्व संकलक को आपके निरंतर उपयोग को टाइप करने की अनुमति देता है।

1

मुख्य अंतर यह है कि #define के साथ आप टाइप सिस्टम छोड़ देते हैं। प्रीप्रोसेसर के पास प्रकार की सुरक्षा, दायरा इत्यादि की कोई धारणा नहीं है, उदाहरण के लिए {...}

आप एक बुरा आश्चर्य कर रहे हैं ...

इसके अलावा, आप बाद में की तरह

(; मीटर < आकार मीटर ++ पूर्णांक मीटर = 0) के लिए

एक पाश लिखने की कोशिश करता है, तो यदि आप # डिफाईन्स का उपयोग करते हैं, तो आपको अपने कोड को डीबग करते समय केवल 30000 का मान दिखाई देगा, न कि m नाम। जो इस मामले में एक बड़ा अंतर नहीं लग रहा है, लेकिन जब सार्थक निरंतर और परिवर्तनीय नामों का उपयोग करते हैं, तो यह वास्तव में करता है।

+0

धन्यवाद। यह डिबगिंग टिप जानना दिलचस्प है। – yCalleecharan

2

...परिवर्तन/हर बार समारोह में कहा जाता है को प्रारंभ

आप शब्दों "परिवर्तन" और "प्रारंभ" के रूप में यद्यपि वे एक ही थे उपयोग करें, लेकिन वे नहीं हैं

void f(void) { 
    static int a = 0; 
    a++; // changed! 
    printf("%d\n", a); 
} 

int main(void) { 
    f(); f(); 
} 

/* 
    # 1 
    # 2 
*/ 

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

तो const के बिना आपका पहला m अभी भी बदला जा सकता है। परिवर्तन के खिलाफ केवल const गार्ड। लेकिन अगर आप static छोड़ देते हैं तो यदि आप लाइब्रेरी या किसी अन्य ऑब्जेक्ट फ़ाइल में लिंक करते हैं जिसमें फ़ाइल-स्कोप पर एक ही गैर स्थैतिक पहचानकर्ता है तो आपको लिंक-टाइम पर संघर्ष मिलेंगे।

2

#define एक प्रीप्रोसेसर ऑपरेशन है और संकलन चरण होने से पहले m की सभी घटनाओं को 30000 द्वारा प्रतिस्थापित किया जाएगा। अन्य दो उदाहरण सच्चे चर हैं। static वैरिएबल अनुवाद इकाई में मौजूद है जिसमें इसे घोषित किया गया है और संशोधित किया जा सकता है। const चर केवल पढ़ने के लिए है।

5

जब आप const double m=3000; लिखते हैं तो आप ऑब्जेक्ट फ़ाइल में m प्रतीक बनाने के लिए कंपाइलर को बता रहे हैं जिसे अन्य फ़ाइलों से एक्सेस किया जा सकता है। संकलक फ़ाइल में m के मान को रेखांकित कर सकता है जहां इसे परिभाषित किया गया है, लेकिन प्रतीक अभी भी में अलग संकलन के प्रयोजनों के लिए आवंटित किया गया है।

जब आप #define m 3000 लिखते हैं तो आप स्रोत फ़ाइल में कई स्थानों पर समान स्थिरता लिखने के लिए सिंटैक्टिक सुविधा का उपयोग कर रहे हैं।

2

आप उपयोग कर सकते हैं m के मूल्य के पाठ्यक्रम हमेशा के लिए एक ही रहने के लिए है, तो है, तो

static const double m = 30000; 

या

#define m 30000 

बस ध्यान दें कि सी में const वस्तुओं डिफ़ॉल्ट रूप से बाह्य संबंध है , इसलिए समतुल्य const घोषणा प्राप्त करने के लिए आपको static const का उपयोग करना होगा, न केवल const

यह भी ध्यान दें कि सी भाषा const वस्तुओं में स्थिरांक नहीं बल्कि "स्थिर चर" हैं। यदि आपको एक सच्चे स्थिर (यानी एक इकाई जो निरंतर अभिव्यक्ति बनाती है) की आवश्यकता है, तो आपको या तो #define या निरंतर निरंतर उपयोग करना होगा।

उत्तरार्द्ध आमतौर पर केवल अभिन्न स्थिरांक के साथ एक मुद्दा है। double के मामले में [static] const के साथ दृष्टिकोण सबसे अच्छा काम कर सकता है।