लॉजिकल एंड सी का यह संस्करण शॉर्ट-सर्किट व्यवहार क्यों नहीं दिखा रहा है?


80

हां, यह एक गृहकार्य का प्रश्न है, लेकिन मैंने अपने शोध और विषय पर गहन विचार किया है और इसका पता नहीं लगा सकता। प्रश्न में कहा गया है कि कोड का यह टुकड़ा शॉर्ट-सर्किट व्यवहार को प्रदर्शित नहीं करता है और पूछता है कि क्यों। लेकिन यह मुझे ऐसा लगता है जैसे यह शॉर्ट-सर्किट व्यवहार को प्रदर्शित करता है, तो क्या कोई समझा सकता है कि यह क्यों नहीं होता है?

सी में:

यह मुझे लगता है कि aझूठे मामले में , कार्यक्रम बिल्कुल मूल्यांकन करने की कोशिश नहीं करेगा b, लेकिन मुझे गलत होना चाहिए। कार्यक्रम bइस मामले में भी क्यों छूता है, जब यह नहीं होता है?


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

49
@RobertHarvey आपको हर समय उत्पादन प्रणालियों में इस तरह कोड दिखाई देगा! यह नाम से एक फ़ंक्शन होने की संभावना नहीं है AND(), लेकिन फ़ंक्शन द्वारा तर्क के आधार पर मान द्वारा तर्क प्राप्त करने और फिर उनका मूल्यांकन (या नहीं) करने वाले फ़ंक्शन हर जगह हैं। एक "ट्रिक प्रश्न" होने के बावजूद, यह समझने के लिए C का एक महत्वपूर्ण व्यवहार है। कॉल-बाय-नाम वाली भाषा में इस प्रश्न का बहुत अलग उत्तर होगा।
बेन जैक्सन

7
@BenJackson: मैं कोड पर टिप्पणी कर रहा था, व्यवहार नहीं। हां, आपको व्यवहार को समझने की जरूरत है। नहीं, आपको इस तरह कोड लिखने की आवश्यकता नहीं है।
रॉबर्ट हार्वे

3
यह वास्तव में काफी प्रासंगिक है यदि आपको कभी वीबी में कोड करना है और आईआईएफ का सामना करना है। क्योंकि यह एक ऑपरेटर के बजाय एक फ़ंक्शन है, मूल्यांकन कम-परिचालित नहीं है। यह शॉर्ट-सर्कुलेटिंग ऑपरेटर के लिए उपयोग किए जाने वाले डेवलपर्स के लिए समस्याएं पैदा कर सकता है, जो तब जैसी चीजें लिखते हैं IIf(x Is Nothing, Default, x.SomeValue)
दान ब्रायंट

3
@ क्योंकि यह शिक्षा प्रणाली का एक अभियोग है।
शिवन ड्रैगन

जवाबों:


118

यह एक ट्रिक प्रश्न है। विधि bका एक इनपुट तर्क है sc_and, और इसलिए हमेशा मूल्यांकन किया जाएगा। दूसरे शब्दों sc_and(a(), b())में कॉल करेंगे a()और कॉल करेंगे b()(ऑर्डर की गारंटी नहीं होगी), फिर sc_andउन परिणामों के साथ कॉल करें a(), b()जिनके पास जाता हैa?b:0 । इसका खुद टर्नरी ऑपरेटर के साथ कोई लेना-देना नहीं है, जो बिल्कुल शॉर्ट-सर्किट होगा।

अपडेट करें

इस संबंध में कि मैंने इसे 'ट्रिक क्वेश्चन' क्यों कहा: यह 'शॉर्ट सर्किटिंग' (कम से कम ओपी द्वारा पुन: प्रस्तुत) पर विचार करने के लिए अच्छी तरह से परिभाषित संदर्भ की कमी के कारण है। कई लोग, जब केवल एक फ़ंक्शन परिभाषा दी जाती है, तो मान लें कि प्रश्न का संदर्भ फ़ंक्शन के शरीर के बारे में पूछ रहा है ; वे अक्सर फ़ंक्शन को अपने आप में एक अभिव्यक्ति के रूप में नहीं मानते हैं। यह प्रश्न की 'ट्रिक' है; आपको याद दिलाने के लिए कि सामान्य रूप से प्रोग्रामिंग में, लेकिन विशेष रूप से सी-लाइक जैसी भाषाओं में, जिनमें अक्सर नियमों के कई अपवाद होते हैं, आप ऐसा नहीं कर सकते। उदाहरण, यदि प्रश्न इस प्रकार पूछा गया था:

निम्नलिखित कोड पर विचार करें। जब मुख्य से बुलाया जाएगा शॉर्ट सर्किट व्यवहार परिहास करना होगा :

यह तुरंत स्पष्ट हो जाएगा कि आप के बारे में सोच होना चाहिए रहे हैं sc_andमें और अपने खुद के में खुद के संचालक के रूप डोमेन विशिष्ट भाषा है, और अगर का मूल्यांकन करने के लिए कॉल sc_andप्रदर्शन शॉर्ट सर्किट व्यवहार एक नियमित रूप से की तरह &&होगा । मैं इस बात पर विचार नहीं करूंगा कि यह एक ट्रिक प्रश्न है, क्योंकि यह स्पष्ट है कि आप टर्नरी ऑपरेटर पर ध्यान केंद्रित करने वाले नहीं हैं, और इसके बजाय C / C ++ के फंक्शन-कॉल मैकेनिक्स पर ध्यान केंद्रित करने वाले हैं (और, मुझे लगता है, लीड होगा sc_andसंक्षेप में एक अनुवर्ती प्रश्न लिखने के लिए कि शॉर्ट-सर्किट करता है, जिसमें #defineफ़ंक्शन के बजाय एक का उपयोग करना शामिल होता है )।

आप खुद को शॉर्ट-सर्कुलेटिंग (या 'सशर्त मूल्यांकन' की तरह कुछ और करते हैं) कॉल करते हैं या नहीं, यह शॉर्ट-सर्कुलेटिंग की आपकी परिभाषा पर निर्भर करता है, और आप उस पर विचारों के लिए विभिन्न टिप्पणियों को पढ़ सकते हैं। मेरे द्वारा यह करता है, लेकिन यह वास्तविक प्रश्न के लिए बहुत प्रासंगिक नहीं है या मैंने इसे 'ट्रिक' क्यों कहा है।


13
टर्नरी ऑपरेटर शॉर्ट-सर्किटिंग करता है? नहीं, यह निम्न में से किसी एक भाव का मूल्यांकन करता है ?, ठीक उसी तरह जैसे if (condition) {when true} else {when-false}। इसे शॉर्ट सर्किटिंग नहीं कहा जाता है।
जेन्स


17
@ जेन्स: मैं किसी भी मामले को कॉल करूँगा जहाँ एक ऑपरेटर अपने एक या अधिक ऑपरेंड्स के मूल्यांकन को "शॉर्ट सर्किटिंग" का रूप देता है, लेकिन यह वास्तव में सिर्फ एक मामला है कि आप शब्द को कैसे परिभाषित करते हैं।
आर .. गिटहब स्टॉप हेल्पिंग ICE

13
@ जेन्स यह एक if elseनहीं, बल्कि एक के लिए सिंथेटिक चीनी है if। और फिर भी, यह वास्तव में नहीं है; ?:ऑपरेटर एक है अभिव्यक्ति , if-elseएक है बयान । वे शब्दार्थ रूप से बहुत भिन्न चीजें हैं, भले ही आप बयानों के समतुल्य सेट का निर्माण कर सकते हैं जो टर्नरी अभिव्यक्ति के समान प्रभाव पैदा करते हैं । यही कारण है कि इसे शॉर्ट-सर्किटिंग माना जाता है; अधिकांश अन्य भाव हमेशा उनके सभी ऑपरेंड ( +,-,*,/आदि) का मूल्यांकन करते हैं । जब वे नहीं करते हैं, तो यह एक शॉर्ट सर्किट ( &&, ||) होता है।
१३:४४

9
हां, मेरे लिए महत्वपूर्ण अंतर यह है कि हम ऑपरेटरों के बारे में बात कर रहे हैं। बेशक फ्लो कंट्रोल स्टेटमेंट कंट्रोल करता है कि कौन सा कोड पथ निष्पादित होता है। ऑपरेटरों के लिए, यह स्पष्ट है कि कोई व्यक्ति सी और सी-व्युत्पन्न भाषाओं से परिचित नहीं है जो एक ऑपरेटर अपने सभी ऑपरेंड का मूल्यांकन नहीं कर सकता है, इसलिए इस संपत्ति के बारे में बात करने के लिए एक शब्द होना जरूरी है, और उसके लिए, मैं "शॉर्ट" का उपयोग करता हूं सर्कुलेटिंग ”।
R .. गिटहब स्टॉप हेल्पिंग ICE

43

जब बयान

निष्पादित, b++मूल्यांकन नहीं किया जाएगा अगर ऑपरेंड का aमूल्यांकन किया गया false(शॉर्ट सर्किट व्यवहार)। इसका मतलब है कि साइड-इफेक्टb नहीं होगा।

अब, फ़ंक्शन को देखें:

और इसे कॉल करें

इस मामले में, क्या aहै trueया false, b++हमेशा फ़ंक्शन कॉल के दौरान 1 का मूल्यांकन किया जाएगा और साइड इफेक्ट bहमेशा होगा।

उसी के लिए सच है

तथा


1 फ़ंक्शन तर्कों के मूल्यांकन के आदेश अनिर्दिष्ट हैं।


1
ठीक है, स्टीफन क्वान के जवाब के साथ इतना सहसंबद्ध: क्या यह संभव है (कानूनी) कि एक कंपाइलर "और_फुन" फ़ंक्शन को इनलाइन कर सकता है, जैसे कि जब आप "बूल एक्स = और_फुन (ए, बी ++;" कहते हैं; अगर सही है तो b ++ बढ़ाई नहीं जाएगी?
शिवन ड्रैगन

4
@ शिवनद्रेगोन यह देखने में लगता है कि मेरे लिए देखने योग्य व्यवहार बदल रहा है।
सपि

3
@ शिवनड्रगन: कंपाइलर को इनलाइन करते समय व्यवहार में बदलाव नहीं होगा। यह केवल फ़ंक्शन बॉडी को प्रतिस्थापित करने के रूप में नहीं है।
जैक एडली

स्पष्टता के लिए, आप int x = a ? b++ : 0अवलोकन योग्य लघु-परिच्छेद के रूप में जोड़ सकते हैं ।
पॉल ड्रेपर

@PaulDraper; मैंने मूल स्निपेट रखा क्योंकि यह पाठकों को भ्रमित करने के लिए नहीं है।
haccks

19

जैसा कि पहले से ही दूसरों द्वारा बताया गया है, दो तर्कों के रूप में कार्य में कोई फर्क नहीं पड़ता, इसका मूल्यांकन किया जाता है क्योंकि यह पास हो जाता है।

दूसरी ओर, यह

होगा यह "के रूप में शॉर्ट सर्किट", मैक्रो एक समारोह कॉल और इस के साथ एक समारोह के तर्क का कोई मूल्यांकन (रों) किया जाता है संकेत नहीं करता है।


शायद क्यों समझा? यह मेरे लिए बिल्कुल op के स्निपेट जैसा दिखता है। एक अलग स्कोप के अपने इनलाइन को छोड़कर।
धिन

5

@Cmasters टिप्पणी में नोट की गई त्रुटियों को ठीक करने के लिए संपादित किया गया।


में

... return एड एक्सप्रेशन शॉर्ट-सर्किट मूल्यांकन प्रदर्शित करता है, लेकिन फ़ंक्शन कॉल नहीं करता है।

कॉल करने का प्रयास करें

फ़ंक्शन कॉल का मूल्यांकन करता है 1 / 0 , हालांकि इसका उपयोग कभी नहीं किया जाता है, इसलिए इसका कारण है - शायद - शून्य त्रुटि से विभाजित।

ANSI C मानक (ड्राफ्ट) से प्रासंगिक अंश हैं:

2.1.2.3 कार्यक्रम का निष्पादन

...

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

तथा

3.3.2.2 फ़ंक्शन कॉल

....

अर्थ विज्ञान

...

किसी फ़ंक्शन को कॉल करने की तैयारी में, तर्कों का मूल्यांकन किया जाता है, और प्रत्येक पैरामीटर को संबंधित तर्क का मान सौंपा जाता है।

मेरा अनुमान है कि प्रत्येक तर्क का मूल्यांकन एक अभिव्यक्ति के रूप में किया जाता है, लेकिन यह कि तर्क की सूची पूरी तरह से एक अभिव्यक्ति नहीं है , इसलिए गैर-एससीई व्यवहार अनिवार्य है।

सी मानक के गहरे पानी की सतह पर एक दिखावा के रूप में, मैं दो पहलुओं पर एक अच्छी तरह से सूचित दृश्य की सराहना करूंगा:

  • क्या मूल्यांकन 1 / 0अपरिभाषित व्यवहार का उत्पादन करता है?
  • क्या एक तर्क एक अभिव्यक्ति की सूची है? (मुझे नहीं लगता)

पी.एस.

यहां तक ​​कि आप C ++ में जाते हैं, और फ़ंक्शन के sc_andरूप में परिभाषित inlineकरते हैं, तो आपको SCE नहीं मिलेगा। यदि आप इसे C मैक्रो के रूप में परिभाषित करते हैं, जैसा कि @alk करता है, तो आप निश्चित रूप से करेंगे।


1
नहीं, एक inlineफ़ंक्शन किसी फ़ंक्शन कॉल के शब्दार्थ को नहीं बदलता है। और वे शब्दार्थ निर्दिष्ट करते हैं कि सभी तर्क हैं मूल्यांकन किया जाता है, जैसा कि आपने सही ढंग से उद्धृत किया है। यहां तक ​​कि अगर कंपाइलर कॉल को ऑप्टिमाइज़ कर सकता है, तो दृश्यमान व्यवहार नहीं बदलना sc_and(f(), g())चाहिए , अर्थात ऐसा व्यवहार करना चाहिए जैसे कि दोनों f()और g()हमेशा कहा जाता है। sc_and(0, 1/0)क्योंकि यह एक बुरा उदाहरण है है अपरिभाषित व्यवहार, और संकलक भी कॉल करने के लिए आवश्यक नहीं है sc_and()...
cmaster - को पुनः स्थापित मोनिका

@ cmaster शुक्रिया। मुझे बस यह नहीं पता था कि C ++ inlineने कॉल शब्दार्थों को संरक्षित किया है। मैं शून्य-विभाजन के साथ फंस गया हूं, क्योंकि यह उदाहरण फिट बैठता है, और SCE मुझे लगता है कि अपरिभाषित व्यवहार से बचने के लिए अक्सर शोषण किया जाता है।
थंबनेल

4

स्पष्ट रूप से त्रिगुट सेशन को देखने के लिए शॉर्ट सर्किटिंग कोड को पूर्णांक के बजाय फ़ंक्शन पॉइंटर्स का उपयोग करने के लिए कोड को थोड़ा बदलने की कोशिश करें:

और फिर इसे संकलित करें (यहां तक ​​कि लगभग कोई अनुकूलन नहीं -O0!)। यदि आप झूठे हैं b()तो आपको निष्पादित नहीं किया जाएगा a()

यहाँ उत्पन्न विधानसभा इस तरह दिखती है:

इसलिए जैसा कि दूसरों ने सही ढंग से कहा है कि प्रश्न चाल को आपको टर्नरी ऑपरेटर व्यवहार पर ध्यान केंद्रित करना है जो कॉल पर पैरामीटर मूल्यांकन के बजाय शॉर्ट सर्किट (कॉल कि 'सशर्त मूल्यांकन') करता है जो कि शॉर्ट सर्किट नहीं है।


0

C टर्नेरी ऑपरेटर कभी भी शॉर्ट-सर्किट नहीं कर सकता है, क्योंकि यह केवल अभिव्यक्ति के लिए दिए गए मान का निर्धारण करने के लिए एक एकल ( a ) स्थिति का मूल्यांकन करता है b और c , यदि कोई मान वापस किया जा सकता है।

निम्नलिखित कोड:

यह निम्नलिखित कोड के लगभग बराबर है:

भाव a तरह && या अन्य ऑपरेटरों द्वारा गठित किया जा सकता है || वह शॉर्ट सर्किट कर सकता है क्योंकि वे एक मूल्य को वापस करने से पहले दो अभिव्यक्तियों का मूल्यांकन कर सकते हैं, लेकिन इसे शॉर्ट-सर्किट करने वाले टर्नरी ऑपरेटर के रूप में नहीं माना जाएगा, लेकिन ऑपरेटर इस स्थिति में उपयोग करते हैं जैसा कि एक नियमित रूप से स्टेटमेंट में होता है।

अपडेट करें:

टर्नरी ऑपरेटर के शॉर्ट-सर्किट ऑपरेटर होने के बारे में कुछ बहस है। तर्क कहता है कि कोई भी ऑपरेटर जो इसका मूल्यांकन नहीं करता है, वह नीचे दिए गए टिप्पणी में @aruisdante के अनुसार शॉर्ट-सर्किट करता है। यदि यह परिभाषा दी जाती है, तो टर्नरी ऑपरेटर शॉर्ट-सर्कुलेटिंग होगा और इस मामले में मूल परिभाषा मैं सहमत हूं। समस्या यह है कि "शॉर्ट-सर्किट" शब्द का उपयोग मूल रूप से एक विशेष प्रकार के ऑपरेटर के लिए किया गया था जिसने इस व्यवहार की अनुमति दी और वे तर्क / बूलियन ऑपरेटर हैं, और यही कारण है कि केवल वही हैं जो मैं समझाने की कोशिश करूंगा।

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

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

जैसा कि मैं सी टर्नरी ऑपरेटर को समझाने की कोशिश कर रहा हूं, जिसे टर्नरी भी कहा जाता है अगर, केवल दो ऑपरेंड का मूल्यांकन करता है, तो यह पहले एक का मूल्यांकन करता है, और फिर एक दूसरे का मूल्यांकन करता है, या तो शेष दो के मूल्य के आधार पर पेहला। यह हमेशा ऐसा करता है, इसका किसी भी स्थिति में तीनों का मूल्यांकन करने वाला नहीं है, इसलिए किसी भी मामले में "शॉर्ट-सर्किट" नहीं है।

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


3
और पतन क्यों? मुझे टिप्पणियाँ पसंद हैं इसलिए मैंने जो कुछ भी कहा है उसे ठीक कर सकता हूं। कृपया रचनात्मक बनें।
एड्रियन पेरेज़

2
शायद -1 क्योंकि यह टॉपिक पर 100% नहीं है। लेकिन वैसे भी मैंने +1 दिया क्योंकि आपका उत्तर कम से कम इसे स्पष्ट बताता है और यह गलत नहीं लगता है।
dhein

4
@ AdrianPerez ने मेरे जवाब में टिप्पणी अनुभाग को देखा कि अधिकांश लोग 100-% को टर्निरीयर ऑपरेटर को शोर-सर्किट क्यों मानते हैं। यह एक अभिव्यक्ति है जो इसके कुछ ऑपरेंड के मूल्य के आधार पर इसके सभी ऑपरेंड का मूल्यांकन नहीं करती है। वह शॉर्ट-सर्किटिंग है।
१३:३३

3
मैं किसी भी गैर-बूलियन ऑपरेटर के बारे में नहीं सोच सकता जो उसके सभी ऑपरेंड का मूल्यांकन नहीं करता है। लेकिन यह बात अलग है; इसका कारण यह है कि इसे शॉर्ट-सर्कुइंग कहा जाता है क्योंकि यह एक ऑपरेटर है (या सामान्य अर्थ में, एक कथन के बजाय एक अभिव्यक्ति) जो इसके सभी ऑपरेंड का मूल्यांकन नहीं करता है। ऑपरेटर का प्रकार वास्तव में मायने नहीं रखता है। बूलियन ऑपरेटरों को लिखना पूरी तरह से संभव होगा जो शॉर्ट सर्किट नहीं थे, और आप गैर-बूलियन वाले भी लिख सकते थे (उदा: पूर्णांक म्यूलिप्लिकटन 0 हमेशा 0 होता है, इसलिए 0 से तुरंत वापस लौटें यदि पहला ऑपरेंड 0 है)।
१०:१४ से

2
x = a ? b : 0;शब्दार्थ है(a && (x = b)) || (x = 0);
jxh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.