Ada tiga alasan.
Pertama-tama, start + (end - start) / 2
berfungsi bahkan jika Anda menggunakan pointer, asalkan end - start
tidak melimpah 1 .
int *start = ..., *end = ...;
int *mid = start + (end - start) / 2; // works as expected
int *mid = (start + end) / 2; // type error, won't compile
Kedua, start + (end - start) / 2
tidak akan meluap jika start
dan end
merupakan angka positif yang besar. Dengan operan yang ditandatangani, overflow tidak ditentukan:
int start = 0x7ffffffe, end = 0x7fffffff;
int mid = start + (end - start) / 2; // works as expected
int mid = (start + end) / 2; // overflow... undefined
(Perhatikan bahwa end - start
mungkin meluap, tetapi hanya jika start < 0
atau end < 0
.)
Atau dengan aritmatika yang tidak ditandatangani, overflow didefinisikan tetapi memberi Anda jawaban yang salah. Namun, untuk operan yang tidak ditandatangani, start + (end - start) / 2
tidak akan pernah meluap selama end >= start
.
unsigned start = 0xfffffffeu, end = 0xffffffffu;
unsigned mid = start + (end - start) / 2; // works as expected
unsigned mid = (start + end) / 2; // mid = 0x7ffffffe
Akhirnya, Anda sering ingin membulatkan ke start
elemen.
int start = -3, end = 0;
int mid = start + (end - start) / 2; // -2, closer to start
int mid = (start + end) / 2; // -1, surprise!
Catatan kaki
1 Menurut standar C, jika hasil pengurangan pointer tidak dinyatakan sebagai a ptrdiff_t
, maka perilaku tidak terdefinisi. Namun, dalam praktiknya, ini membutuhkan mengalokasikan char
array menggunakan setidaknya setengah dari seluruh ruang alamat.
(start + end)
mungkin meluap, sementara(end - start)
tidak bisa.