इसके तीन कारण हैं।
सबसे पहले, start + (end - start) / 2
काम करता है , भले ही आप पॉइंटर्स का उपयोग कर रहे हों, जब तक कि end - start
अतिप्रवाह 1 नहीं होता है ।
int *start = ..., *end = ...;
int *mid = start + (end - start) / 2; // works as expected
int *mid = (start + end) / 2; // type error, won't compile
सभी में से एक, start + (end - start) / 2
अतिप्रवाह नहीं होगा start
और end
बड़ी सकारात्मक संख्याएं हैं। हस्ताक्षरित ऑपरेंड के साथ, अतिप्रवाह अपरिभाषित है:
int start = 0x7ffffffe, end = 0x7fffffff;
int mid = start + (end - start) / 2; // works as expected
int mid = (start + end) / 2; // overflow... undefined
(ध्यान दें कि end - start
अतिप्रवाह हो सकता है, लेकिन केवल अगर start < 0
या end < 0
।)
या अहस्ताक्षरित अंकगणित के साथ, अतिप्रवाह परिभाषित किया गया है लेकिन आपको गलत उत्तर देता है। हालांकि, अहस्ताक्षरित ऑपरेंड के लिए, start + (end - start) / 2
कभी भी अतिप्रवाह नहीं होगा end >= start
।
unsigned start = 0xfffffffeu, end = 0xffffffffu;
unsigned mid = start + (end - start) / 2; // works as expected
unsigned mid = (start + end) / 2; // mid = 0x7ffffffe
अंत में, आप अक्सर start
तत्व की ओर चक्कर लगाना चाहते हैं ।
int start = -3, end = 0;
int mid = start + (end - start) / 2; // -2, closer to start
int mid = (start + end) / 2; // -1, surprise!
फुटनोट
1 सी मानक के अनुसार, यदि सूचक घटाव का परिणाम एक के रूप में प्रतिनिधित्व करने योग्य नहीं है ptrdiff_t
, तो व्यवहार अपरिभाषित है। हालांकि, व्यवहार में, इसके लिए char
कम से कम आधे पूरे पते की जगह का उपयोग करके एक सरणी आवंटित करने की आवश्यकता होती है।
(start + end)
अतिप्रवाह हो सकता है, जबकि(end - start)
नहीं।