फ़ाइल स्कोप पर भिन्न रूप से संशोधित सरणी


85

मैं अपने ऑब्जेक्टिव-सी कार्यान्वयन फ़ाइल में उपयोग होने वाली एक स्थिर स्टेटिक सरणी बनाना चाहता हूं जो मेरे ".m" फ़ाइल के शीर्ष पर कुछ इस तरह हो।

static const int NUM_TYPES = 4;
static int types[NUM_TYPES] = { 
  1,
  2, 
  3, 
  4 };

मैं NUM_TYPESबाद में फ़ाइल में उपयोग करने की योजना बना रहा हूं इसलिए मैं इसे एक चर में रखना चाहता था।

हालाँकि, जब मैं ऐसा करता हूं, मुझे त्रुटि मिलती है

"फ़ाइल स्कोप पर वैरिएंट 'संशोधित' प्रकार"

मैं इकट्ठा करता हूं कि यह कुछ हो सकता है कि सरणी का आकार एक चर है (मुझे यह संदेश नहीं मिलता है जब मैंने एक पूर्णांक शाब्दिक रखा, जैसे static int types[4])।

मैं इसे ठीक करना चाहता हूं, लेकिन शायद मैं इसके बारे में गलत कर रहा हूं ... मेरे यहां 2 लक्ष्य हैं:

  1. एक सरणी है, जो फ़ाइल में उपलब्ध है
  2. NUM_TYPESएक चर में encapsulate करने के लिए तो मैं एक ही शाब्दिक अपनी फ़ाइल में विभिन्न स्थानों के बारे में बिखरे हुए नहीं है

कोई सुझाव?

[EDIT] सी फाक में यह पाया गया: http://c-faq.com/ansi/constasconst.html


2
यदि आप इसे एक परिभाषित के रूप में करते हैं तो क्या होता है? #define kNUM_TYPES 4?
जॉर्ज इजराइल Peña

यह काम करता है ... किसी कारण से मैं प्रीप्रोसेसर का उपयोग करने से दूर रहने की कोशिश कर रहा था क्योंकि मुझे लगा कि मुझे यह याद है कि मैंने कहीं पढ़ा था, लेकिन मैंने अभी कुछ और शोध किया और इस मामले में इसका उपयोग नहीं करने का एक अच्छा कारण नहीं मिल सका। मुझे लगता है कि यह कम वांछनीय हो सकता है यदि मैं प्रीप्रोसेसर में वस्तुओं का निर्माण कर रहा हूं (जैसे @"An NSString literal") केवल आपके कोड के टुकड़े के साथ गलत बात यह है कि अर्धविराम की कोई आवश्यकता नहीं है।
सैम

आह हाँ, सिर के लिए धन्यवाद, और खुशी है कि मैं मदद कर सकता था।
जॉर्ज इजराइल Peña

जवाबों:


62

इस चेतावनी का कारण यह है कि c में कॉन्स्टेंट का मतलब स्थिर नहीं है। इसका अर्थ है "केवल पढ़ने के लिए"। तो मान एक मेमोरी पते पर संग्रहीत किया जाता है और संभवतः मशीन कोड द्वारा बदला जा सकता है।


3
परिभाषित एक वस्तु को संशोधित करना const(जैसे कि constएक पॉइंटर से दूर और एक मूल्य को संग्रहीत करना) अपरिभाषित व्यवहार है; इसलिए, ऐसी वस्तु का मूल्य एक संकलन-समय या रन-टाइम स्थिरांक (भंडारण अवधि के आधार पर) है। मान का उपयोग स्थिर अभिव्यक्ति में नहीं किया जा सकता है क्योंकि C मानक यह नहीं कहता है कि यह हो सकता है। ( constयदि किसी ऑब्जेक्ट को बिना constडायनेमिक या आबंटित किया गया है तो स्ट्रिंग constको
हटाने

3
@jilles "को मशीन कोड द्वारा संभावित रूप से बदला जा सकता है" का अर्थ यह नहीं है कि इस उत्तर के लेखक का अर्थ "सी कोड द्वारा संभावित रूप से बदला जा सकता है"। इसके अलावा, इसका एक और बहुत अच्छा कारण है: externविभिन्न टीयू में स्थिरांक हो सकते हैं , जिनमें से वर्तमान टीयू को संकलित करते समय मूल्य ज्ञात नहीं होता है।

14
इस उत्तर को बेहतर बनाने का एक तरीका यह दिखाना होगा कि इस मुद्दे को कैसे हल किया जाए।
जॉर्ज स्टॉकर

32

यदि आप अन्य उत्तरों के अनुसार, वैसे भी प्रीप्रोसेसर का उपयोग करने जा रहे हैं, तो आप कंपाइलर को ऑटोमैटिक तरीके से निर्धारित कर सकते हैं NUM_TYPES:

#define NUM_TYPES (sizeof types / sizeof types[0])
static int types[] = { 
  1,
  2, 
  3, 
  4 };

वाह, यह वास्तव में अच्छा है ... मुझे नहीं पता था कि यह संभव था। मुझे लगता है कि इस गणना की लागत नगण्य है। क्या मैं यह भी मान सकता हूं कि एक संकलक इसे स्थिर मूल्य पर अनुकूलित कर सकता है?
सैम सैम

2
हाँ, इस sizeofतरह की वस्तुओं का परिणाम एक संकलन-समय स्थिर है।
कैफे



4

जैसा कि यह पहले से ही अन्य उत्तरों में समझाया गया है, constसी में केवल इसका मतलब है कि एक चर केवल-पढ़ने के लिए है। यह अभी भी एक रन-टाइम मूल्य है। हालाँकि, आप enumC में वास्तविक स्थिरांक के रूप में उपयोग कर सकते हैं :

enum { NUM_TYPES = 4 };
static int types[NUM_TYPES] = { 
  1, 2, 3, 4
};

3

Imho यह कई सी संकलकों में एक दोष है। मैं एक तथ्य के लिए जानता हूं कि मैंने जो संकलक के साथ काम किया, वह एक "स्थिर कास्ट" वैरिएबल को एक एड्रेस पर संग्रहीत नहीं करता है, लेकिन कोड में उपयोग को बहुत स्थिर द्वारा प्रतिस्थापित करता है। जब आप एक प्रीप्रोसेसर #define निर्देश का उपयोग करते हैं और जब आप एक स्थिर कॉन्स्टेबल वैरिएबल का उपयोग करते हैं तो यह सत्यापित किया जाएगा कि आपको उत्पादित कोड के लिए समान चेकसम मिलेगा।

किसी भी तरह से आपको जब भी संभव हो, #defines के बजाय स्थिर कॉन्स्टेबल वैरिएबल का उपयोग करना चाहिए क्योंकि स्टैटिक कास्ट सुरक्षित है।


यह बहुत बुरा लगता है, क्योंकि आप एक static constचर का पता ले सकते हैं । आपके द्वारा वर्णित व्यवहार एक मान्य अनुकूलन हो सकता है, लेकिन यह निश्चित रूप से ऐसा कुछ नहीं है जो हमेशा काम कर सकता है।
खोलना

यह वास्तव में ठीक है। C कंपाइलर के लिए कास्ट ग्लोबल वैरिएबल्स के व्यक्तिगत उपयोगों को जहां भी संभव हो, निरंतर मूल्य के साथ प्रतिस्थापित करना ठीक है। यदि एक चर के सभी संदर्भों को स्थिरांक में बदल दिया जाता है, तो संकलक इसे पूरी तरह से हटा सकता है। यदि आप कहीं भी पते का उपयोग करते हैं, तो उसे हटाया नहीं जाएगा। इनमें से कोई भी परिवर्तन नहीं करता है कि भाषा मानक के अनुसार, C किसी वैरिएबल के साथ वैश्विक सरणियों को आकार के रूप में अनुमति नहीं देता है, चाहे चर कांस्टेबल हो या न हो।
इवान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.