2010-06-28 7 views
12

संभव डुप्लिकेट:
Why use enum when #define is just as efficient?# परिभाषित या enum?

जब सी में प्रोग्रामिंग, यह एक राज्य मशीन में राज्यों के लिए #define बयान या enums उपयोग करने के लिए बेहतर अभ्यास है?

+6

जिन प्रश्नों के उत्तर "एक 'परिभाषित करें' पसंद करते हैं, वे आश्चर्यजनक रूप से कम हैं। – Stephen

+1

@ स्टीफन: अधिकतर क्योंकि कई पोस्टर सी ++ मोड में लॉक होते हैं, जबकि सवाल सी के बारे में है। इस संबंध में सी और सी ++ के बीच का अंतर इतना बड़ा है। वास्तव में, ज्यादातर मामलों में सी में आपको '# परिभाषित' करना चाहिए, लेकिन इस विशिष्ट मामले में (राज्य मशीन) 'enum' वास्तव में एक बेहतर दृष्टिकोण है। – AnT

+0

जहां तक ​​मुझे याद है, कुछ डुप्लिकेट। शायद "राज्य मशीन में राज्यों के लिए" कल्पना, इसे थोड़ा सा बदलती है, लेकिन "राज्य मशीन की स्थिति" पर विचार करने का कोई कारण नहीं है कि # परिभाषा या enums का एक अलग अनुप्रयोग के लिए इस्तेमाल किया जा सकता है ... – ShinTakezou

उत्तर

12

चूंकि राज्य संबंधित तत्व हैं, इसलिए मुझे लगता है कि उन्हें परिभाषित करने के लिए बेहतर है।

8

मैं enum पसंद करते हैं। वे अधिक कॉम्पैक्ट हैं और 'सुरक्षित' हैं। आप एक enum में आदेश भी लागू कर सकते हैं, जो एक राज्य मशीन में सहायक हो सकता है। यदि संभव हो तो # डिफाइन से बचा जाना चाहिए, क्योंकि वे स्रोत में सभी घटनाओं को ओवरराइट कर देंगे, जिससे कुछ अनजान कार्रवाइयां हो सकती हैं जिन्हें डीबग करना मुश्किल होता है।

2

#define निर्देशों में बहुत से अनपेक्षित परिणाम हो सकते हैं और सामान्य स्कोपिंग नियमों का पालन नहीं करते हैं। जब आपके पास संबंधित डेटा है तो enums का उपयोग करें।

अधिक जानकारी: http://www.embedded.com/columns/programmingpointers/9900402?_requestid=341945 [सी ++ सामग्री, लेकिन अभी भी मामूली रूप से प्रासंगिक]

+0

आपको जानकारी लिंक सी ++ के बारे में है, सी नहीं। सी और सी ++ के बीच अंतर जब स्थिरांक को परिभाषित करने के लिए एक विधि चुनने की बात आती है * विशाल *। – AnT

+0

परवाह किए बिना, यदि संभव enums बेहतर हैं क्योंकि वे टाइप-सुरक्षित हैं और किसी भी अन्य कोड को ओवरराइट नहीं करते हैं –

+1

@ नाथन फ़ेलमैन: नहीं सी में, 'enum' केवल तभी बेहतर होता है जब हम स्थिरांक के प्राकृतिक समूह के साथ काम कर रहे हों। अन्य सभी मामलों में यह 'परिभाषित 'है और केवल' # परिभाषित 'है। – AnT

2

तो enum अपने संकलक के द्वारा समर्थित है, तो उस को प्राथमिकता दी जाएगी। ऐसा लगता है कि, हर तरह से, #define का उपयोग करें। सभी सी ++ कंपाइलर्स और आधुनिक सी कंपाइलर्स को enum का समर्थन करना चाहिए, लेकिन पुराने कंपाइलर्स (विशेष रूप से एम्बेडेड प्लेटफॉर्म को लक्षित करने वाले) enum का समर्थन नहीं कर सकते हैं।

आप उपयोग करना आवश्यक है #define, पूर्वप्रक्रमक त्रुटियों से बचने के कोष्ठकों के साथ अपने स्थिरांक परिभाषित करने के लिए सुनिश्चित करें:

#define RED_STATE (1) 
#define YELLOW_STATE (2) 
#define GREEN_STATE (3) 
9

कोई निश्चित जवाब नहीं है। enum आपको स्कोपिंग और स्वचालित मान असाइनमेंट प्रदान करता है, लेकिन निरंतर प्रकार (हमेशा signed int) पर कोई नियंत्रण नहीं देता है। #define स्कोपिंग को अनदेखा करता है, लेकिन आपको बेहतर टाइपिंग सुविधाओं का उपयोग करने की अनुमति देता है: आपको निरंतर प्रकार चुनने देता है (या तो प्रत्यय का उपयोग करके या परिभाषा में स्पष्ट कलाकार सहित)।

तो, अपने लिए चुनें कि आपके लिए क्या अधिक महत्वपूर्ण है। एक राज्य मशीन के लिए, enum एक बेहतर विकल्प हो सकता है, जब तक कि आपके पास इस प्रकार को नियंत्रित करने का कोई अच्छा कारण न हो।

+0

अधिकांश कंपाइलर आपको enums के आकार को निर्दिष्ट करने की अनुमति देते हैं। –

+1

@ एडम शिमेके: ... जो आम तौर पर एक वैश्विक सेटिंग है। और मैं इस आकार के बारे में बात कर रहा हूं, आकार के बारे में नहीं। न तो सी और न ही सी ++ (इसके वर्तमान रूप में) आपको एनम मूल्यों के प्रकार पर कोई सार्थक नियंत्रण प्रदान करता है। – AnT

+0

AFAIR C99 आपको 'enum' स्थिरांक के प्रकार के लिए कोई विकल्प नहीं देता है, अर्थात् यह उन्हें' हस्ताक्षरित int 'प्रकार के स्थिरांक के रूप में ठीक करता है। एक 'enum' प्रकार की एक अलग चौड़ाई हो सकती है, और यह एक सुविधाजनक आकार चुनने के लिए कंपाइलर पर निर्भर करता है जैसे कि प्रकार के साथ परिभाषित सभी स्थिरांक फिट बैठता है। इसलिए विशेष रूप से आपके पास उस आकार को 'int' के मुकाबले छोटा हो सकता है लेकिन आमतौर पर बड़ा नहीं होता है। –

0

enum महान आप अनन्य विकल्प हैं जब है, लेकिन आप इस तरह, bitfield झंडे परिभाषित करने के लिए उनका उपयोग नहीं कर सकते हैं:

paint_square(SQ_WITH_RED | SQ_WITH_BLUE); 
:

#define SQ_DEFAULT 0x0 
#define SQ_WITH_RED 0x1 
#define SQ_WITH_BLUE 0x2 

void paint_square(int flags); 

तो फिर तुम साथ लाल नीले वर्ग पेंट कर सकते हैं

... जो आप enum के साथ नहीं कर सकते हैं।

+0

हाँ आप कर सकते हैं: 'enum (a = 1, b = 2, c = 4, d = 5)' –

+2

नहीं कर सकता? बेशक, आप यह कर सकते हैं: 'enum {SQ_DEFAULT = 0x0, SQ_WITH_RED = 0x1, SQ_WITH_BLUE = 0x2}'। यहां समस्या यह है कि झंडे के साथ * असाइन किए गए * प्रकार का उपयोग करना बेहतर होता है। लेकिन अन्यथा, enum काम करेगा। – AnT

+1

निश्चित रूप से आप कर सकते हैं! 'enum रंग {डिफ़ॉल्ट = 0x0, लाल = 0x1, नीला = 0x2}; 'और बाद में' paint_square (लाल | नीला)' – Mecki

36

तकनीकी रूप से इससे कोई फर्क नहीं पड़ता। संकलक सबसे अधिक संभावना भी किसी भी स्थिति के लिए समान मशीन कोड निर्माण करेंगे, लेकिन एक गणन तीन फायदे हैं:

  1. सही संकलक + डिबगर संयोजन का उपयोग करना, डिबगर उनकी गणना नाम से गणन चर प्रिंट होगा और नहीं द्वारा अपने नंबर। तो "स्टेटब्लैबब्लुप" "41" से बहुत अच्छा पढ़ता है, है ना?

  2. आपने स्पष्ट रूप से प्रत्येक राज्य को एक नंबर नहीं दिया है, तो संकलक आपके लिए नंबरिंग करता है यदि आप इसे देते हैं। आइए मान लीजिए कि आपके पास पहले से ही 20 राज्य हैं और आप परिभाषित होने के मामले में मध्य में एक नया राज्य जोड़ना चाहते हैं, आपको अपने आप को सभी renumbering करना होगा। गणना के मामले में, आप केवल राज्य जोड़ सकते हैं और संकलक आपके लिए इस नए राज्य के नीचे सभी राज्यों की मरम्मत करेगा।

  3. आप कंपाइलर को चेतावनी देने के लिए कह सकते हैं कि कोई स्विच स्टेटमेंट सभी संभावित एनम मानों को संभाल नहीं सकता है, उदा। क्योंकि आप कुछ मूल्यों को संभालने के लिए भूल गए हैं या क्योंकि enum बढ़ाया गया था, लेकिन आप enum मानों को संभालने वाले स्विच स्टेटमेंट को भी अपडेट करना भूल गए हैं (हालांकि default केस होने पर यह चेतावनी नहीं देगा, क्योंकि सभी मान स्पष्ट रूप से डिफ़ॉल्ट मामले में समाप्त नहीं होते हैं) ।

+5

अच्छा जवाब ... +1 – wrapperm

0

आप जो भी चाहें और पसंद कर सकते हैं उसका उपयोग कर सकते हैं।

फिर भी हर कोई कह रहा है कि मैं भी मुझे एम्स के लिए वोटिंग के रूप में जोड़ना चाहूंगा।

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

आगे की enums आपके प्रोग्राम को सुरक्षित रखेगी क्योंकि सभी enums केवल इसके प्रकार के होंगे, इसलिए वे किसी भी संभावित भ्रम से बचेंगे।

# परिभाषा का उपयोग राज्य मशीन या संबंधित डेटा के मामले में नहीं किया जाना चाहिए। वैसे भी मेरा सुझाव है, लेकिन कोई कठोर और तेज़ नियम नहीं है।

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

1

आप इस चाल को #define मान के प्रकार की जांच करने के लिए कर सकते हैं।

#define VALUE_NAME ((TYPE_NAME) 12) 

हालांकि #define की वास्तविक समस्या यह आवेदन कोड में नए सिरे से परिभाषित किया जा सकता है। (बेशक कंपाइलर आपको इसके बारे में चेतावनी देगा।)