তিনটি কারণ রয়েছে।
প্রথমত, 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
কমপক্ষে পুরো ঠিকানা স্পেস ব্যবহার করে একটি অ্যারে বরাদ্দ করা দরকার requires
(start + end)
ওভারফ্লো হতে পারে, যখন(end - start)
পারে না।