有三个原因。
首先,即使您使用指针,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 + (end - start) / 2 不会溢出。对于有符号操作数,溢出是未定义的:
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 根据 C 标准,如果指针减法的结果不能表示为 ptrdiff_t,则行为未定义。然而,在实践中,这需要使用至少一半的整个地址空间来分配char 数组。