यदि यह कथन-असाइनमेंट और एक इक्विटी चेक के संयोजन को सही क्यों बनाता है?


216

मैं कुछ शुरुआती गलतियों के बारे में सोच रहा हूं और मैं ifबयान पर एक के साथ समाप्त हुआ । मैंने इस कोड को थोड़ा विस्तारित किया:

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}

मैंने देखा है कि ifबयान रिटर्न सही है, और यह cout's iके रूप में 1। यदि यदि स्टेटमेंट में iअसाइन 1किया गया है, तो क्यों i == 0लौटा true?


83
दोस्तों, यह टाइपो प्रश्न नहीं है। ओपी जानना चाहता है कि अगर इस कोड के साथ iसेट किया गया है तो क्यों स्टेटमेंट दर्ज किया गया है 1
नाथनऑलिवर

24
या इसका परिणाम बताता है 1 && i == 0?
JVApen

4
शुरुआती लोगों के लिए सुझाव: उन्हें इस तरह के "उन्नत" भाषा निर्माण का उपयोग नहीं करना चाहिए। बस चर को अलग से असाइन करें। यह भी अनुक्रम बिंदु के साथ संभावित समस्याओं से बचना होगा। व्यावहारिक कोड में इस तरह का कोड आमतौर पर बुरा भी लगेगा।
user202729

1
यह एक साक्षात्कार प्रश्न पर समाप्त होने के लिए बाध्य है
RAZ_Muh_Taz

जवाबों:


391

यह ऑपरेटर पूर्वता के साथ करना है

if (i = 1 && i == 0)

नहीं है

if ((i = 1) && (i == 0))

क्योंकि दोनों &&और ==की तुलना में अधिक पूर्वता है =। यह वास्तव में क्या काम करता है

if (i = (1 && (i == 0)))

जो का परिणाम बताती 1 && (i == 0)है i। तो, अगर iमें शुरू होता है 0तो i == 0है true, इसलिए 1 && trueहै true(या 1), और फिर iकरने के लिए सेट हो जाता है 1। तब से 1यह सत्य है, यदि आप ब्लॉक को दर्ज करते हैं और आपके द्वारा निर्दिष्ट मूल्य को प्रिंट करते हैं i


2
@ JörgWMittag यह बहुत अच्छा है। मुझे पसंद है कि यह आपको कोष्ठक का उपयोग करने के लिए मजबूर करता है।
नाथनऑलिवर

मूल रूप से, i = !i; if (i)ठीक से लिखा गया है
काकाहुइट फ्रिटो

@NathanOliver: किले एक बहुत अच्छी भाषा थी जो बहुत सारी चीजों को सही कर देती थी। (प्रमुख डिजाइनर गाइ एल। स्टील थे, इसलिए इसमें कोई आश्चर्य नहीं है।) दुर्भाग्य से, यह DARPA फंडिंग के अंतिम दौर के लिए नहीं उठाया गया था, और बाद में ओरेकल द्वारा mothballed किया गया था।
जोर्ज डब्ल्यू मित्तग

6
स्वाभाविक रूप से, संकलक से चेतावनियों के बारे में पूछने पर उस त्रुटि का पता चल जाता,
Deduplicator

4
कोई भी भाषा जो चींटियों और बूलियन के बराबर नहीं है, वह भी इसे उठाएगी।
रगोम

16

आपके कोड को वास्तव में इस तरह देखता है:

#include <iostream>
using namespace std;

int main()  {
    int i = 0;
    if (i = 1 && i == 0) {
        cout << i;
    }
}

फिर यह:

if (i = 1 && i == 0) {

के रूप में मूल्यांकन करता है

 if (i = (1 && i == 0)) {

और ऐसा iकरने के लिए तैयार है 1


39
क्या अतिरिक्त कोड वास्तव में आवश्यक था? यह बहुत स्पष्ट लगता है कि यह मामला होगा क्योंकि यह अन्यथा नहीं चलेगा।
मॉडलमैट

13
न केवल अनावश्यक अतिरिक्त कोड। उत्तर स्पष्ट रूप से ऑपरेटर पूर्वता को स्पष्ट करने में विफल रहता है।
फ्रांसिस्को ज़ाराबोज़ो

34
जब से हम निपिक ट्रेन पर हैं ... मैं देख रहा हूँ using namespace std!
मतीन उल्हाक

8
अतिरिक्त कोड है - लेकिन यह अभी भी गलत कोड नहीं है। और जवाब अभी भी सही है। बेशक, यह ऑपरेटर की पूर्वता की व्याख्या नहीं करता है। लेकिन कोई इसे सीधे-सीधे मतदान के बजाय, जोड़े जाने का सुझाव दे सकता है!
बी चार्ल्स एच

14
वाह, -4 कठोर है, इस प्रश्न पर सही ढंग से उत्तर देते हुए, हालांकि शायद आशावादी नहीं है। यह ऑपरेटर की पूर्ववर्तीता पर उतना विस्तार नहीं करता है, जितना कि अन्य उत्तर में, लेकिन यह कोड के संदर्भ में इसके बारे में इतना ही कहता है कि जो कोई भी यह सोचता है कि =इससे पहले आया &&मुद्दा देख सकता है। इसके अलावा, हाँ, विस्तार अतिरंजित है, लेकिन मुझे नहीं लगता कि यह इतना मायने रखता है। मैं विश्वास नहीं कर सकता कि इस तरह के मामूली अंतर के कारण लोग 151 से -4 वोट देते हैं।
जोएल

-4

यह बाएं से दाएं नियमों को पार्स करने के साथ करना है। जैसे y = x + 5।
सभी उप-अभिव्यक्तियों को महत्व दिया जाता है। समान महत्व के दो भावों का मूल्यांकन दाईं से बाईं ओर किया जाता है, && अभिव्यक्ति पक्ष पहले किया जाता है, उसके बाद LHS।

मेरी समझ मे आ रहा है।


1
सहानुभूति ("बाएं से दाएं नियम") का इससे कोई लेना-देना नहीं है। यह पूर्वता ("महत्व") के बारे में है, और उपयोग किए गए ऑपरेटरों में समान पूर्वता नहीं है।
ऑर्बिट में हल्कापन दौड़

-4

वास्तविक उत्तर है:

  1. संकलक "i == 0" को पूर्वता देता है , जो सत्य का मूल्यांकन करता है।
  2. फिर यह TRUE या FALSE के रूप में i = 1 का मूल्यांकन करेगा, और चूंकि संकलित असाइनमेंट ऑपरेटर कभी भी विफल नहीं होते हैं (अन्यथा वे संकलन नहीं करेंगे), यह भी सच का मूल्यांकन करता है।
  3. चूंकि दोनों कथन सत्य के रूप में मूल्यांकन करते हैं, और TRUE && TRUE TRUE का मूल्यांकन करता है, यदि कथन कथन TRUE का मूल्यांकन करेगा।

प्रमाण के रूप में, बस आपके द्वारा दर्ज किए गए कोड के लिए अपने संकलक के asm आउटपुट को देखें (सभी टिप्पणियाँ मेरी अपनी हैं):

mov     dword ptr [rbp - 8], 0    ; i = 0;
cmp     dword ptr [rbp - 8], 0    ; i == 0?
sete    al                        ; TRUE (=1)
mov     cl, al
and     cl, 1                     ; = operator always TRUE
movzx   edx, cl
mov     dword ptr [rbp - 8], edx  ; set i=TRUE;
test    al, 1                     ; al never changed,
                                  ; so final ans is TRUE

ऊपर का asm आउटपुट CLANG से था, लेकिन अन्य सभी कंपाइलरों पर मैंने समान आउटपुट दिया। यह उस साइट के सभी संकलक के लिए सही है, चाहे वे शुद्ध सी या सी ++ संकलक हों, सभी बिना किसी संकलक के संकलक के मोड को बदलने के लिए (जो डिफ़ॉल्ट रूप से C ++ संकलक के लिए C ++ है)

ध्यान दें कि आपके कंपाइलर ने वास्तव में i = 1 सेट नहीं किया था, लेकिन i = TRUE (जिसका अर्थ है कोई भी 32-बिट शून्य पूर्णांक मान नहीं)। ऐसा इसलिए है क्योंकि && ऑपरेटर केवल मूल्यांकन करता है कि कोई कथन TRUE है या FALSE है, और फिर उस परिणाम के अनुसार परिणाम सेट करता है। प्रमाण के रूप में, i = 1 से i = 2 को बदलने का प्रयास करें और आप अपने लिए देख सकते हैं कि कुछ भी नहीं बदलेगा। कंपाइलर एक्सप्लोरर में किसी भी ऑनलाइन कंपाइलर का उपयोग करके अपने लिए देखें


1
1) डॉक्स सी ऑपरेटर पूर्ववर्ती से लिंक करता है, जब यह प्रश्न C ++ के साथ टैग किया जाता है। दो अलग-अलग भाषाएँ। 2 ए) i = 1एक असाइनमेंट है [एक समतुल्य नहीं] ऑपरेटर; 2 बी) मैं आपको आश्वासन दे सकता हूं कि if (i = 0)सी और सी ++ दोनों में झूठी स्थिति का मूल्यांकन करेंगे, इसलिए क्या यह सच्चे wrt का मूल्यांकन करता है "यह कभी विफल नहीं होता है" कुछ भ्रामक है।
ट्रेब्लडजे

1
and cl, 1 ; = operator always TRUE<< गलत होने पर मुझे सही करें, लेकिन मुझे यहां कोई असाइनमेंट नहीं दिखता है। यह 1 &&अभिव्यक्ति के हिस्से का प्रतिनिधित्व करता है । तो यह उत्तर मूल रूप से मूल्यांकन करता है false
syck

"डॉक्स सी ऑपरेटर की पूर्वता से लिंक करता है, जब इस प्रश्न को C ++ दो अलग-अलग भाषाओं के साथ टैग किया जाता है" - और जब आप C की C C ++ ऑपरेटर पूर्वता से तुलना करते हैं, तो दोनों में क्या अंतर है? इस विषय के संबंध में उनकी एक ही मिसाल है, जो आश्चर्यजनक नहीं है, क्योंकि C ++ सी का प्रत्यक्ष व्युत्पन्न है (या इसे लगाने का दूसरा तरीका है, C C ++ भाषा का सबसेट है, इसलिए निश्चित रूप से उनके पास होगा पूर्व में बहुत कुछ शामिल है)। मैं अपनी पोस्ट को वैसे भी ठीक करूंगा, जो भ्रामक है।
ar18

"अगर मैं गलत हूं तो मुझे सुधारो, लेकिन मुझे यहां कोई काम नहीं दिखता" - फिर मुझे आपको सही करने दें! 1 एक तत्काल मूल्य है और किसी भी परीक्षण या गणना का परिणाम नहीं है। यह वह है जिसे "प्रकल्पित TRUE" मान कहा जाता है। इकलौती परीक्षा जो i == 0 स्टेटमेंट के लिए होती है, वह है - "cmp dword ptr [rbp - 8], 0"। आप केवल तभी सही होंगे जब उसने "movzx edx, 1" कहा हो। मेरे से पहले के सभी पदों के अनुसार, दो तुलनाएँ होनी चाहिए, लेकिन वास्तविक जीवन में केवल एक ही है, और हर प्रमुख कंपाइलर का asm आउटपुट यह साबित करता है कि ये पोस्ट पूरी तरह से गलत हैं।
ar18

2
पूर्ववर्ती गलत होने के साथ-साथ (सही पार्सिंग के लिए NathanOliver का उत्तर देखें), आप यह गलत दावा करते हैं कि असाइनमेंट ऑपरेटर हमेशा TRUE में रहता है। कोशिश करो if ( i = 0 ) { print something }। इसके अलावा आपका जवाब खुद ही विरोधाभासी है; प्रारंभ में आप कहते हैं कि लागू i=1होने &&से पहले मूल्यांकन किया जाता है, और फिर अंत में आप कहते हैं कि ऑपरेटर iके परिणाम पर सेट है &&
एमएम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.