2009-09-16 10 views
44

मुझे पता है कि यह कम से कम बेवकूफ या अच्छी शैली है, सी में #define के बजाय enum एस के रूप में संख्यात्मक स्थिरांक घोषित करने के लिए।सी में स्ट्रिंग स्थिरांक कैसे घोषित करते हैं?

/* bad style */ 
#define MAXLINE 1024 

/* good/better style */ 
enum { 
    MAX_LINE = 1024 
}; 

स्ट्रिंग स्थिरांक की परिभाषा के लिए एक समान नियम है?

/* is this good style? */ 
#define HELLO "Hello World" 

/* or is this better? */ 
const char *HELLO2 = "Howdy"; 

आप क्या पसंद करते हैं? यदि संभव हो तो किसी भी विधि के कुछ दोष दिखाएं।

उत्तर

70

एक और (कम से कम) रोम के लिए सड़क है:

static const char HELLO3[] = "Howdy"; 

(static - वैकल्पिक - यह अन्य फ़ाइलों के साथ परस्पर विरोधी से रोकने के लिए है)। मैं इसे const char* से अधिक पसंद करूंगा, क्योंकि तब आप sizeof(HELLO3) का उपयोग करने में सक्षम होंगे और इसलिए आपको संकलन समय पर रनटाइम तक स्थगित करने की आवश्यकता नहीं है।

परिभाषा संकलन-समय संगतता का लाभ है, हालांकि (HELLO ", World!" सोचें) और आप sizeof(HELLO) भी कर सकते हैं।

लेकिन फिर आप const char* भी पसंद कर सकते हैं और इसे एकाधिक फ़ाइलों में उपयोग कर सकते हैं, जो आपको स्मृति का एक मोर्सल बचाएगा।

संक्षेप में - यह निर्भर करता है।

+0

आपकी स्पष्टीकरण के लिए धन्यवाद। निरंतर पूर्णांक मानों के लिए मैक्रो स्थिरांक या 'const int 'के बजाय' enum 'का उपयोग करने का कारण यह तथ्य है कि यह निरंतर पूर्णांक घोषित करने का एकमात्र प्रकार-सुरक्षित तरीका है जिसे पोर्टेबल को सरणी सीमा के रूप में उपयोग किया जा सकता है। खैर ... संकलन समय स्ट्रिंग concatenation लगभग मुझे स्ट्रिंग के लिए '# परिभाषा' का उपयोग करने पर बेच दिया, लेकिन लागू होने पर 'स्थिर 'का उपयोग कर प्रकार सुरक्षा के लिए मैं' const char * 'पर चिपके रहूंगा। संक्षेप में मैं सभी शेष के लिए पूर्णांक स्थिरांक और 'const' चर के लिए 'enum' का उपयोग करूंगा। –

+1

टैट, मैं सुझाव दूंगा कि आप किसी भी चीज़ से चिपके रहें। * सभी स्थिरांक बराबर * नहीं हैं। यदि आप एकजुट नहीं होने जा रहे हैं, तो आपको # परिभाषित करने की आवश्यकता नहीं है, अगर आपको आकार की आवश्यकता नहीं है, तो आपको बिल्कुल परवाह नहीं है। जो मैं पूरी तरह से देखने में असफल रहा वह यह है कि 'कॉन्स्ट चार *' बेहतर होता है तो 'const char [] '* जहां स्थिर लागू होता है *। लेकिन फिर, यदि आपको आकार की आवश्यकता नहीं है, तो यह कोई भी बुरा नहीं है ;-) –

9

एक लाभ यह (बहुत मामूली यद्यपि) स्ट्रिंग को परिभाषित करने स्थिरांक की है कि आप उन्हें जोड़ सकते हैं:

 
#define HELLO "hello" 
#define WORLD "world" 

puts(HELLO WORLD); 

यकीन है कि ऐसा नहीं है कि वास्तव में एक फायदा है, लेकिन यह एक तकनीक है कि स्थिरांक चार के साथ नहीं किया जा सकता है * के।

3

#define विधि का मुख्य नुकसान यह है कि प्रत्येक बार जब इसका उपयोग किया जाता है तो स्ट्रिंग को डुप्लिकेट किया जाता है, ताकि आप इसे निष्पादन योग्य में बहुत सारी प्रतियों के साथ समाप्त कर सकें, जिससे इसे बड़ा बना दिया जा सके।

+5

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

+2

यह सच है, जब तक कि संकलक या लिंकर प्रतियों को एक में ढहता नहीं है। इस सुविधा को कभी-कभी "स्ट्रिंग पूलिंग" कहा जाता है – Rom

-2

पहले के लिए। Enums डिफ़ॉल्ट पूर्णांक से हैं, इसका मतलब है कि आप केवल उस मान को पास कर सकते हैं जो केवल पूर्णांक स्वीकार करता है।

दूसरा मुझे बेहतर पसंद है: #define के बजाय const char * संस्करण। कारण यह है कि सी में सरणी पॉइंटर्स हैं, जिसका अर्थ यह है कि प्रत्येक बार जब आप # परिभाषित संस्करण का उपयोग करना चाहते हैं, तो आपको इसका उपयोग करने के लिए इस स्ट्रिंग को तुरंत चालू करना होगा।

+1

सरणी पॉइंटर्स नहीं हैं और जब स्ट्रिंग स्थिरता की बात आती है तो "स्ट्रिंग इंस्टेंटेशन" की कोई अवधारणा नहीं होती है। और यदि सरणी पॉइंटर्स थे तो इसका मतलब यह नहीं होगा कि स्ट्रिंग को तत्काल भी किया जाना चाहिए, ऐसी चीज भी थी ;-) –

+0

वह संख्यात्मक स्थिरांक के बारे में बात कर रहा था। Arrays हमें संदर्भ के रूप में पारित कर दिया जाता है कम से कम मैं ऐसा करने के लिए अन्य तरीका नहीं समझ सकता। तो। इस मामले में डिफ़ॉल्ट वापसी क्या है? { कॉन्स char * str1 = हेल्लो; कॉन्स char * str1 = हेल्लो; वापसी (str1 == str2); } –

+0

रिटर्न वैल्यू कार्यान्वयन पर निर्भर है, लेकिन (मान लीजिए कि आप दूसरे असाइनमेंट में str2 का मतलब है) अधिकांश कार्यान्वयन सच हो जाएंगे - इसे आज़माएं, दोनों पॉइंटर्स निरंतर डेटा सेगमेंट में एक ही स्ट्रिंग का संदर्भ लेंगे। लेकिन इस कोड के पास सरणी के साथ कुछ लेना देना नहीं है, यह सादा सूचक है। पॉइंटर के रूप में सरणी पास करने के लिए, यह इंगित नहीं करता है कि सरणी * पॉइंटर्स हैं। 'int *' और 'int [2] 'विभिन्न प्रकार हैं। और न केवल सैद्धांतिक रूप से - आप समझदारी से 'sizeof()' सूचक नहीं कर सकते हैं, आप सरणी नहीं बढ़ा सकते हैं, आदि 0 में –

7

आप एक "स्थिरांक स्ट्रिंग" चाहते हैं अपने प्रश्न का कहना है की तरह, मैं सच में संस्करण आप अपने प्रश्न में कहा गया है के लिए जाना होगा:

/* first version */ 
const char *HELLO2 = "Howdy"; 

विशेष रूप से, मैं से बचने होगा:

/* second version */ 
const char HELLO2[] = "Howdy"; 

कारण: दूसरे संस्करण के साथ समस्या यह है कि कंपाइलर पूरी स्ट्रिंग "हाउडी" की एक प्रतिलिपि बनायेगा, प्लस कि स्ट्रिंग संशोधित है (इसलिए वास्तव में नहीं है)।

दूसरी तरफ, पहला संस्करण कॉन्स्ट पॉइंटर हेल्लो 2 द्वारा उपलब्ध एक कॉन्स स्ट्रिंग है, और कोई भी इसे संशोधित करने का कोई तरीका नहीं है।

+5

मुझे लगता है कि 'कॉन्स char * const HELLO2' बेहतर है .. – Shawn

संबंधित मुद्दे