टर्नरी ऑपरेटर का उपयोग मैक्रो में 1 और 0 को परिभाषित करने के लिए क्यों किया जाता है?


79

मैं एक एम्बेडेड परियोजना के लिए एक एसडीके का उपयोग कर रहा हूं। इस सोर्स कोड में मुझे कुछ कोड मिले जो कम से कम मुझे अजीबोगरीब लगे। एसडीके में कई स्थानों पर इस प्रारूप में स्रोत कोड है:

#define ATCI_IS_LOWER( alpha_char )  ( ( (alpha_char >= ATCI_char_a) && (alpha_char <= ATCI_char_z) ) ? 1 : 0 )

#define ATCI_IS_UPPER( alpha_char )  ( ( (alpha_char >= ATCI_CHAR_A) && (alpha_char <= ATCI_CHAR_Z) ) ? 1 : 0 )

क्या यहां टर्नरी ऑपरेटर के इस्तेमाल से कोई फर्क पड़ता है?

नहीं है

#define FOO (1 > 0)

बराबर

#define BAR ( (1 > 0) ? 1 : 0)

?

मैंने इसका उपयोग करके मूल्यांकन करने की कोशिश की

printf("%d", FOO == BAR);

और परिणाम 1 प्राप्त करते हैं, इसलिए ऐसा लगता है कि वे समान हैं। क्या कोड लिखने का कोई कारण है जैसा उन्होंने किया था?


8
नहीं, कोई कारण नहीं है। तुम सही हो।
आर्ट

29
आंशिक रूप से ऑफ-टॉपिक: प्रीप्रोसेसर का उपयोग करने का पागलपन कब बंद हो जाता है? यहां शामिल कार्यों के संभावित कई मूल्यांकन हैं। बस अनावश्यक है।
स्टीफन

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

5
बहुत कम से कम, मैक्रोज़ को (alpha_char)इसके बजाय का उपयोग करना चाहिए alpha_char, बस यह सुनिश्चित करने के लिए कि यह टूट न जाए अगर कोई किसी पागल की तरह कोशिश करता हैATCI_IS_LOWER(true || -1)
जस्टिन टाइम -

5
ऐसा लगता है कि सीआई ने बहुत पहले लिखा था। मैं पास्कल से सी के लिए आया था, जो एक समर्पित booleanप्रकार था, इसलिए मैंने अनजाने समय को भयावह रूप से बदलते हुए बर्बाद कर if (n)दिया if (0 != n), शायद एक संदिग्ध कलाकार को "सुनिश्चित करने के लिए" जोड़ना। मुझे यकीन है कि मैंने भी बुलेट-प्रूफ असमानताओं को पसंद किया if (a < b) ...है। यकीन है कि यह पास्कल की तरह लगif a < b then ... रहा था, लेकिन मुझे पता था कि सी < एक नहीं था , booleanलेकिन एक int, और लगभग कुछ भीint हो सकता है ! भय सोने की परत चढ़ता है, सोना चढ़ाता है व्यामोह की ओर जाता है, व्यामोह की ओर जाता है ... जैसे कोड।
केविन जे। चेस

जवाबों:


131

आप सही हैं, C में यह टॉटोलोगस है। आपके दोनों विशेष टर्नरी सशर्त और (1 > 0) प्रकार के हैं int

लेकिन यह होगा C ++ में कोई फर्क हालांकि, कुछ जिज्ञासु कोने मामलों में (जैसे अतिभारित कार्यों के लिए पैरामीटर के रूप में), के बाद से अपने त्रिगुट सशर्त अभिव्यक्ति प्रकार का है int, जबकि (1 > 0)प्रकार का है bool

मेरा अनुमान है कि लेखक ने C ++ अनुकूलता को संरक्षित करने के लिए एक आँख के साथ कुछ विचार रखा है।


2
मुझे लगा कि bool <-> intरूपांतरण सी + + में )4.7 / 4 मानक (अभिन्न रूपांतरण) से निहित हैं, तो यह कैसे होगा?
मोटून

70
एक फ़ंक्शन के दो अधिभार पर विचार करें foo, एक const bool&दूसरे को लेने वाला ए const int&। उनमें से एक आपको भुगतान करता है, अन्य सुधार आपकी हार्ड डिस्क। आप यह सुनिश्चित करना चाहते हैं कि आप उस स्थिति में सही अधिभार कह रहे हैं।
बथशेबा

3
यह इस मामले को संभालने के लिए और अधिक स्पष्ट नहीं होना चाहिए न कि परिणाम को intटर्नरी का उपयोग करके?
मार्टिंकव

18
@ बाथशीबा एक वैध कोने के मामले में, कोई भी प्रोग्रामर जो इस तरह के असंगत व्यवहार को लागू करने के लिए अभिन्न अतिभार का उपयोग करता है, पूरी तरह से बुराई है।
JAB

7
@ जेएबी: आपको बुराई करने की ज़रूरत नहीं है, आपको बस कोड के एक टुकड़े को लिखने की आम (आम) गलती करनी होगी जो गलती से दो अलग-अलग चीजों को करता है (या इससे भी बदतर, अपरिभाषित व्यवहार को लागू करता है) अभिन्न प्रकार पर निर्भर करता है, और है। एक जगह पर ऐसा करने का दुर्भाग्य है जो मौलिक रूप से विभिन्न कोड पथों को ट्रिगर कर सकता है।

28

लाइनिंग टूल हैं जो इस राय के हैं कि तुलना का परिणाम बूलियन है, और इसका उपयोग सीधे अंकगणित में नहीं किया जा सकता है।

नाम या किसी भी उंगलियों को इंगित करने के लिए नहीं, लेकिन पीसी-लिंट एक ऐसा उपकरण है

मैं यह नहीं कह रहा कि वे सही हैं, लेकिन यह एक संभावित स्पष्टीकरण है कि कोड को इस तरह क्यों लिखा गया था।


10
Not to name names or point any fingers,लेकिन तुम दोनों की तरह था, योग्य।
स्टैकऑवरफ्लो

19

आप कभी-कभी इसे बहुत पुराने कोड में देख सकते हैं , इससे पहले कि सी (x > y)1 या 0 का मूल्यांकन करने के लिए सी मानक था ; कुछ सीपीयू इसके बजाय to1 या 0 का मूल्यांकन करते हैं, और कुछ बहुत पुराने कंपाइलरों का अभी-अभी अनुसरण किया जा सकता है, इसलिए कुछ प्रोग्रामर को लगा कि उन्हें अतिरिक्त सुरक्षा की आवश्यकता है।

आप कभी-कभी इसे भी देखेंगे क्योंकि समान भाव जरूरी संख्यात्मक 1 या 0. का मूल्यांकन नहीं करते हैं । उदाहरण के लिए, में

#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) ? 1 : 0)

आंतरिक- &एक्सप्रेशन या तो 0 या संख्यात्मक मान का मूल्यांकन करता है F_DO_GRENFELZ, जो कि शायद 1 नहीं है , इसलिए ? 1 : 0इसे विहित करने के लिए कार्य करता है। मुझे व्यक्तिगत रूप से यह स्पष्ट है कि यह लिखना है

#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) != 0)

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


पूरे पर मैं !!( expr )एक बूलियन canonicalise का उपयोग करना पसंद करता हूं , लेकिन मैं यह स्वीकार करूंगा कि यदि आप इससे परिचित नहीं हैं तो यह भ्रामक है।
PJTraill

1
@PJTraill हर बार जब आप अपने कोष्ठकों के अंदर जगह बनाते हैं, तो भगवान एक बिल्ली का बच्चा मारता है। कृप्या। बिल्ली के बच्चे के बारे में सोचो।
zwol

मैंने सी प्रोग्राम में कोष्ठक के अंदर रिक्त स्थान नहीं रखने का सबसे अच्छा कारण सुना है।
PJTraill

15

एसडीके कोड में एक बग है, और टर्नरी शायद इसे ठीक करने के लिए एक कीचड़ था।

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

#define IS_LOWER( x ) ( ( (x >= 'a') && (x <= 'z') ) ?  1 : 0 )
std::cout << IS_LOWER('A' && 'c');
**1**
std::cout << IS_LOWER('c' && 'A');
**0**

यही कारण है कि एक को हमेशा विस्तार में स्थूल तर्कों को कम करना चाहिए।

तो आपके उदाहरण में (लेकिन मापदंडों के साथ), ये दोनों खराब हैं।

#define FOO(x) (x > 0)
#define BAR(x) ((x > 0) ? 1 : 0)

वे सबसे सही ढंग से प्रतिस्थापित किया जाएगा

#define BIM(x) ((x) > 0)

@CiaPan निम्नलिखित टिप्पणी में एक महान बिंदु बनाता है जो यह है कि एक से अधिक पैरामीटर का उपयोग करने से एक बार परिणाम अपरिहार्य हो जाता है। उदाहरण के लिए

#define IS_LOWER( x ) (((x) >= 'a') && ((x) <= 'z'))
char ch = 'y';
std::cout << IS_LOWER(ch++);
**1** 
**BUT ch is now '{'**

4
: एक और बग कि पैरामीटर, दो बार प्रयोग किया जाता है तो साइड इफेक्ट के साथ एक बहस अप्रत्याशित परिणाम के लिए नेतृत्व करेंगे है IS_LOWER(++ var)बढ़ाने के हो सकते हैं var, एक या दो बार अतिरिक्त यह नोटिस नहीं हो सकता और लोअर केस पहचान 'z'करता है, तो varथा 'y'मैक्रो कॉल करने से पहले। इसीलिए ऐसे मैक्रों से बचना चाहिए, या किसी फ़ंक्शन के तर्क को आगे बढ़ाया जाना चाहिए।
सियापन

5

सी में यह कोई फर्क नहीं पड़ता। C में बूलियन अभिव्यक्तियों के प्रकार intऔर एक मान है जो 0या तो है 1, इसलिए

ConditionalExpr ? 1 : 0

कोई प्रभाव नहीं है।

C ++ में, यह प्रभावी रूप से एक कास्ट है int, क्योंकि C ++ में सशर्त अभिव्यक्ति प्रकार है bool

#include <stdio.h>
#include <stdbool.h>

#ifndef __cplusplus

#define print_type(X) _Generic(X, int: puts("int"), bool: puts("bool") );

#else
template<class T>
int print_type(T const& x);
template<> int print_type<>(int const& x) { return puts("int"); }
template<> int print_type<>(bool const& x) { return puts("bool"); }


#endif

int main()
{
    print_type(1);
    print_type(1 > 0);
    print_type(1 > 0 ? 1 : 0);

/*c++ output:
  int 
  int 
  int

  cc output:
  int
  bool
  int
*/

}

यह भी संभव है कि कोई प्रभाव का इरादा नहीं था, और लेखक ने सोचा कि यह कोड को स्पष्ट कर देगा।


BTW, मुझे लगता है कि C को सुइट का पालन करना चाहिए और बूलियन एक्सप्रेशन बनाने चाहिए _Bool, अब C के पास है _Boolऔर _Generic। यह बहुत ज्यादा कोड को नहीं तोड़ना चाहिए जो सभी छोटे प्रकार के ऑटोप्रोमोट को intसबसे अधिक संदर्भों में वैसे भी देता है।
PSkocik

5

एक सरल व्याख्या यह है कि कुछ लोग या तो यह नहीं समझते हैं कि कोई शर्त C में समान मान लौटाएगी, या वे सोचते हैं कि यह लिखना साफ है ((a>b)?1:0)

यही कारण है कि कुछ भी उचित बूलियन के साथ भाषाओं में इसी तरह के निर्माण का उपयोग करते हैं, जो कि सी-सिंटैक्स में होगा (a>b)?true:false)

यह भी बताता है कि आपको इस मैक्रो को क्यों नहीं बदलना चाहिए।


0

हो सकता है, एक एम्बेडेड सॉफ्टवेयर होने के नाते, कुछ सुराग दे। हो सकता है कि इस शैली का उपयोग करते हुए कई मैक्रोज़ लिखे गए हों, यह आसान संकेत देने के लिए कि एसीटीआई लाइनें उल्टे तर्क के बजाय सीधे तर्क का उपयोग करती हैं।

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