क्या प्रीप्रोसेसर निर्देश का उपयोग करना बेहतर है या यदि (स्थिर) कथन है?


10

मान लें कि हमारे पास एक कोडबेस है जो कई अलग-अलग कॉस्ट्यूमर्स के लिए उपयोग किया जाता है, और हमारे पास इसमें कुछ कोड है जो केवल टाइप X के कॉस्ट्यूमर्स के लिए प्रासंगिक है। क्या इस कोड को केवल टाइप X के कॉस्ट्यूमर में शामिल करने के लिए प्रीप्रोसेसर निर्देशों का उपयोग करना बेहतर है, या यदि कथन का उपयोग करना है? स्पष्ट होने के लिए:

// some code
#if TYPE_X_COSTUMER  = 1
// do some things
#endif
// rest of the code

या

if(TYPE_X_COSTUMER) {
    // do some things
}

मैं जिन तर्कों के बारे में सोच सकता हूं वे हैं:

  • प्रीप्रोसेसर निर्देश छोटे कोड पदचिह्न और कम शाखाओं में (गैर-अनुकूलन वाले संकलक पर)
  • यदि कथन ऐसे कोड के साथ परिणाम देता है जो हमेशा संकलित करता है, उदाहरण के लिए यदि कोई ऐसी गलती करेगा जो उस परियोजना के लिए अप्रासंगिक कोड को नुकसान पहुंचाएगा जो वह काम करता है, तो त्रुटि अभी भी दिखाई देगी, और वह कोड आधार को भ्रष्ट नहीं करेगा। अन्यथा वह भ्रष्टाचार से अवगत नहीं होगा।
  • मुझे हमेशा कहा गया था कि प्रीप्रोसेसर के उपयोग पर प्रोसेसर के उपयोग को प्राथमिकता दें (यदि यह एक तर्क है ...)

बेहतर क्या है - जब कई अलग-अलग कॉस्ट्यूमर्स के लिए कोड आधार के बारे में बात की जाती है?


3
आप एक अनुकूलन कंपाइलर का उपयोग करके बनाए गए निर्माण को शिप नहीं करेंगे, तो क्या होगा? और अगर ऐसा होता है, तो क्या प्रभाव मामला (विशेषकर जब आपके द्वारा याद किए गए अन्य सभी अनुकूलन के संदर्भ में रखा जाएगा)?

@delnan - इस कोड का उपयोग कई अलग-अलग प्लेटफार्मों के लिए कई अलग-अलग संकलक के साथ किया जाता है। और प्रभाव के बारे में - यह कुछ मामलों में हो सकता है।
MBDD

आपको कुछ पसंद करने के लिए कहा गया था? यह किसी को KFC से खाना खाने के लिए मजबूर करने जैसा है जबकि उसे चिकन पसंद नहीं है।
राइटफॉल्ड

@WTP - नहीं, मैं नहीं था, मुझे और जानने की दिलचस्पी है, इसलिए मैं भविष्य में बेहतर निर्णय लूंगा।
एमबी

अपने दूसरे उदाहरण में, क्या TYPE_X_CUSTOMERअभी भी एक प्रीप्रोसेसर मैक्रो है?
detly

जवाबों:


5

मुझे लगता है कि #define का उपयोग करने का एक फायदा है जिसका आपने उल्लेख नहीं किया है, और वह यह है कि आप कमांड लाइन पर मान सेट कर सकते हैं (इस प्रकार, इसे अपने वन-स्टेप बिल्ड स्क्रिप्ट से सेट करें)।

इसके अलावा, आम तौर पर मैक्रोज़ से बचना बेहतर होता है। वे किसी भी ढकोसले का सम्मान नहीं करते हैं और इससे समस्याएं पैदा हो सकती हैं। केवल बहुत डंब कंपाइलर एक संकलन-समय स्थिरांक के आधार पर एक स्थिति का अनुकूलन नहीं कर सकते हैं। मुझे नहीं पता कि आपके उत्पाद के लिए यह चिंता का विषय है (उदाहरण के लिए एम्बेडेड प्लेटफार्मों पर कोड को छोटा रखना महत्वपूर्ण हो सकता है)।


वास्तव में, यह है एम्बेडेड प्रणाली के लिए
MByD

समस्या यह है कि एम्बेडेड सिस्टम आमतौर पर कुछ प्राचीन संकलक का उपयोग कर रहे हैं (उदाहरण के लिए gcc 2.95)।
19

@ वीजेओ - जीसीसी भाग्यशाली मामला है :)
एमबीवाईडी

इसे तब आजमाएँ। यदि इसमें अप्रयुक्त कोड शामिल है और यह काफी आकार का है, तो परिभाषित के लिए जाएं।
तमसे सजेलेई

यदि आप संकलक कमांड लाइन के माध्यम से इसे सेट करने में सक्षम होना चाहते हैं, तो मैं अभी भी कोड में एक स्थिरांक का उपयोग करूँगा और उस स्थिरांक को दिए गए मान को केवल #define करूंगा।
कोड इंचेचोस

12

कई प्रश्नों के लिए, इस प्रश्न का उत्तर निर्भर करता है । यह कहने के बजाय कि जो बेहतर है मैंने उसके उदाहरण और लक्ष्य दिए हैं जहां एक दूसरे से बेहतर है।

प्रीप्रोसेसर और स्थिरांक दोनों के उपयुक्त उपयोग के अपने स्थान हैं।

प्री-प्रोसेसर के मामले में, संकलन समय से पहले कोड हटा दिया जाता है। इसलिए, यह उन परिस्थितियों के लिए सबसे उपयुक्त है जहां कोड की उम्मीद नहीं है । यह मॉड्यूल संरचना, निर्भरता को प्रभावित कर सकता है, और यह प्रदर्शन पहलुओं के लिए सर्वश्रेष्ठ कोड सेगमेंट चुनने की अनुमति दे सकता है। निम्नलिखित मामलों में, किसी को केवल प्रीप्रोसेसर के उपयोग से कोड को विभाजित करना होगा।

  1. बहु-प्लेटफ़ॉर्म कोड:
    उदाहरण के लिए, जब कोड को विभिन्न प्लेटफार्मों के तहत संकलित किया जाता है, जब कोड में ओएस के विशिष्ट संस्करण संख्याओं पर निर्भरता होती है (या यहां तक ​​कि संकलक संस्करण - हालांकि यह बहुत दुर्लभ है)। उदाहरण के लिए जब आप कोड के छोटे-एंडियन बड़े-एंडियन समकक्षों के साथ काम कर रहे हैं - तो उन्हें स्थिरांक के बजाय पूर्वप्रक्रमकों के साथ अलग किया जाना चाहिए। या यदि आप विंडोज के लिए कोड के रूप में अच्छी तरह से लिनक्स और कुछ सिस्टम कॉल बहुत अलग हैं संकलन कर रहे हैं।

  2. प्रायोगिक पैच:
    एक अन्य मामला जहां यह सुनिश्चित करता है कि कुछ प्रायोगिक कोड है जो कि जोखिम भरा है या कुछ प्रमुख मॉड्यूल जिन्हें छोड़ा जाना आवश्यक है जिनमें महत्वपूर्ण लिंकिंग या प्रदर्शन अंतर होगा। कारण अगर कोई () के तहत छिपाने के बजाय प्रीप्रोसेसर के माध्यम से कोड को अक्षम करना चाहेगा , क्योंकि हम इस विशिष्ट परिवर्तन सेट द्वारा शुरू किए गए बग के बारे में सुनिश्चित नहीं हो सकते हैं और हम प्रयोगात्मक आधार पर चल रहे हैं। यदि यह विफल रहता है, तो हमें फिर से लिखने के बजाय उत्पादन में उस कोड को अक्षम करने के अलावा और कुछ नहीं करना चाहिए । पूरे कोड को कमेंट करने के लिए उपयोग करने के लिए कुछ समय आदर्श है ।#if 0

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

  4. लाइसेंसिंग:
    प्रीप्रोसेसर निर्देश के उदाहरण का एक बहुत दिलचस्प ffmpeg है । इसमें कोडेक्स हैं जो संभावित रूप से इसके उपयोग से पेटेंट का उल्लंघन कर सकते हैं। यदि आप स्रोत डाउनलोड करते हैं और इंस्टॉल करने के लिए संकलन करते हैं, तो यह आपसे पूछता है कि क्या आप चाहते हैं या इस तरह के सामान को दूर रखें। कुछ शर्तों के तहत कोड छिपाए रखना अगर अभी भी स्थिति आपको अदालत में ला सकती है!

  5. कोड कॉपी-पेस्ट:
    आका मैक्रोज़। यह मैक्रोज़ का उपयोग करने के लिए एक सलाह नहीं है - बस मैक्रोज़ के पास कॉपी-पास्ट समकक्ष लागू करने का अधिक शक्तिशाली तरीका है । लेकिन इसे बहुत सावधानी से उपयोग करें; और इसका उपयोग करें यदि आप जानते हैं कि आप क्या कर रहे हैं। बेशक, ऐसा नहीं कर सकते। लेकिन एक inlineकार्य का उपयोग कर सकते हैं अगर ऐसा करना आसान है।

तो आप स्थिरांक का उपयोग कब करते हैं?
लगभग हर जगह।

  1. निटर कोड प्रवाह:
    सामान्य तौर पर, जब आप स्थिरांक का उपयोग करते हैं, तो यह नियमित रूप से चर से लगभग अप्रभेद्य होता है और इसलिए, यह बेहतर पठनीय कोड है। यदि आप रूटीन लिखते हैं जो कि 75 पंक्तियाँ हैं - # 10 के बाद हर 10 पंक्तियों के बाद 3 या 4 पंक्तियाँ हैं, तो यह पढ़ने में असमर्थ है । संभवतः #ifdef द्वारा शासित एक प्राथमिक निरंतरता दी गई है, और हर जगह एक प्राकृतिक प्रवाह में इसका उपयोग करें।

  2. अच्छी तरह से इंडेंटेड कोड: सभी प्रीप्रोसेसर निर्देश, अन्यथा अच्छी तरह से इंडेंट कोड के साथ कभी भी काम नहीं करते हैं । यहां तक ​​कि अगर आपका कंपाइलर #def के इंडेंटेशन की अनुमति देता है, तो प्री-एएनएसआई सी प्रीप्रोसेसर ने एक लाइन की शुरुआत और "#" चरित्र के बीच जगह की अनुमति नहीं दी; अग्रणी "#" को हमेशा पहले कॉलम में रखा जाना चाहिए था।

  3. कॉन्फ़िगरेशन:
    एक और कारण है कि स्थिरांक या चर समझ में आता है कि वे आसानी से ग्लोबल्स से जुड़े होने से विकसित हो सकते हैं या भविष्य में कॉन्फ़िगरेशन फ़ाइलों से प्राप्त किए जा सकते हैं।

एक आखिरी बात:
कभी भी यूएसई प्रीप्रोसेसर के दायरे #ifdefको #endifपार करने के निर्देश नहीं या { ... }। के विभिन्न पक्षों पर यानी की शुरुआत #ifdefया अंत । यह बेहद खराब है; यह भ्रामक हो सकता है, यह कभी-कभी खतरनाक हो सकता है।#endif{ ... }

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


लंबे और विस्तृत उत्तर के लिए धन्यवाद। मुझे आपके द्वारा बताई गई अधिकांश चीजों के बारे में पता था और वे इस सवाल से बच गए थे कि सवाल यह नहीं है कि क्या प्रीप्रोसेसर क्षमताओं का उपयोग करना है, बल्कि एक विशेष प्रकार के उपयोग के बारे में भी। लेकिन मुझे लगता है कि आपके द्वारा बनाया गया मूल बिंदु सत्य है।
एमबीडी

1
"कभी भी USE प्रीप्रोसेसर के निर्देश #ifdef से #endif को स्कोप या {...} से पार नहीं करता है" यह IDE पर निर्भर करता है। यदि IDE निष्क्रिय प्रीप्रोसेसर ब्लॉकों को पहचानता है और उन्हें अलग करता है या अलग-अलग रंग दिखाता है, तो यह भ्रमित करने वाला नहीं है।
अब्येक

@ यह सही है कि आईडीई मदद कर सकता है। हालाँकि, कई मामलों में जहां लोग * निक्स (लिनक्स इत्यादि) प्लेटफॉर्म के तहत विकसित होते हैं - संपादकों आदि की पसंद कई हैं (VI, emacs और इसी तरह)। तो हो सकता है कि कोई और आपसे अलग संपादक का उपयोग कर रहा हो।
दीपन मेहता

4

क्या आपके ग्राहकों के पास आपके कोड तक पहुंच है? यदि हाँ, तो प्रीप्रोसेसर बेहतर विकल्प हो सकता है। हमारे पास कुछ समान है और हम विभिन्न ग्राहक (या ग्राहक विशिष्ट सुविधाओं) के लिए संकलन समय झंडे का उपयोग करते हैं। फिर एक स्क्रिप्ट ग्राहक विशिष्ट कोड निकाल सकती है और हम उस कोड को शिप करते हैं। ग्राहक अन्य ग्राहकों या अन्य ग्राहक विशिष्ट विशेषताओं के बारे में नहीं जानते हैं।


3

उल्लेख के योग्य कुछ अतिरिक्त बिंदु:

  1. कंपाइलर कुछ प्रकार के निरंतर अभिव्यक्तियों को संसाधित कर सकता है जो प्रीप्रोसेसर नहीं कर सकता है। उदाहरण के लिए, प्रीप्रोसेसर में आमतौर sizeof()पर गैर-आदिम प्रकारों के मूल्यांकन का कोई तरीका नहीं होता है। यह if()कुछ मामलों में उपयोग को मजबूर कर सकता है ।

  2. कंपाइलर कोड में सबसे अधिक वाक्यविन्यास के मुद्दों को नजरअंदाज करेगा जो #if(कुछ प्रीप्रोसेसर-संबंधित समस्या अभी भी परेशानी पैदा कर सकता है) में छोड़ दिया जाता है, लेकिन कोड के लिए सिंटैक्टिक शुद्धता पर जोर देते हैं if()। इस प्रकार, अगर कोड जो कुछ बिल्ड के लिए छोड़ दिया जाता है, लेकिन अन्य नहीं फाइल में परिवर्तन के परिणामस्वरूप अवैध हो जाता है (उदाहरण के लिए पहचानकर्ताओं का नाम) यह आम तौर पर सभी बिल्ड पर स्क्वॉक करेगा यदि यह अक्षम है if()लेकिन नहीं तो यह अक्षम है #if। इस पर निर्भर करता है कि कोड क्यों छोड़ा जा रहा है, यह अच्छी बात हो सकती है या नहीं।

  3. कुछ संकलक अप्राप्य कोड को छोड़ देंगे, जबकि अन्य नहीं करेंगे; अनुपलब्ध कोड के भीतर स्थिर भंडारण अवधि की घोषणाएं, हालांकि, स्ट्रिंग शाब्दिकों सहित, स्थान आवंटित कर सकती हैं, भले ही कोई कोड कभी भी आवंटित स्थान का उपयोग न कर सके।

  4. मैक्रोज़ if()उनके भीतर परीक्षणों का उपयोग कर सकते हैं , लेकिन प्रीप्रोसेसर के लिए कोई तंत्र नहीं है कि मैक्रो के भीतर किसी भी सशर्त तर्क को निष्पादित करने के लिए [ध्यान दें कि मैक्रोज़ के भीतर उपयोग के लिए, ? :ऑपरेटर अक्सर बेहतर हो सकता है if, लेकिन समान सिद्धांत लागू होते हैं]।

  5. #ifनिर्देश क्या मैक्रो निर्धारित हो नियंत्रित करने के लिए इस्तेमाल किया जा सकता।

मुझे लगता if()है कि ज्यादातर मामलों के लिए अक्सर क्लीनर होता है, सिवाय इसके कि जो कंपाइलर उपयोग कर रहा है या मैक्रोज़ को परिभाषित किया जाना चाहिए, उसके आधार पर निर्णय लेना शामिल है; उपरोक्त मुद्दों में से कुछ का उपयोग करने की आवश्यकता हो सकती है #if, हालांकि, यहां तक ​​कि उन मामलों में जहां ifक्लीनर प्रतीत होता है।


1

लंबी कहानी छोटी: प्रीप्रोसेसर निर्देशों के बारे में आशंकाएं मूल रूप से 2 हैं, कई समावेशन और शायद कम पठनीय कोड और अधिक गंभीर तर्क।

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


यह एक महान कोड आधार है, और परिभाषित वास्तव में कुछ अलग हेडर में हैं।
एमबीडी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.