二进制搜索访问超出范围索引

时间:2016-09-02 07:31:22

标签: c arrays algorithm search

这是代码:

char binarySearch(unsigned int target, int* primes, unsigned int size){
    int* ptrToArray = primes;
    unsigned int first = 0;
    unsigned int last = size;

    while (first <= last){
        unsigned int middle = first + (last - first) / 2;
        printf("first: %d, last: %d, middle: %d\n", first, last , middle);

        if (ptrToArray[middle] == target){
            return 1;
        }

        if (ptrToArray[middle] < target){
            first = middle + 1;
        }else{
            last = middle - 1;
        }
    }
    return 0;
}

这是输出:

enter image description here

我一直盯着不止一个代码的和平,但仍然无法弄清楚这个缺陷在哪里。

4 个答案:

答案 0 :(得分:3)

如果middle0,则在调试输出的末尾附近,语句为

last = middle - 1

导致整数溢出;条件必须重新修改。

答案 1 :(得分:3)

问题在于您将索引变量(firstlastmiddle)定义为unsigned int,而在您的逻辑中,last实际上可以变得消极。但是,在这种情况下,由于它们被定义为unsigned,并且由于负数的2的补码表示方式有效,因此while循环中的条件仍然正确。

请查看以下示例代码以进行说明:

#include <stdio.h>

int main() {
  /* defining the variables as unsigned */
  unsigned int first_u = 0;
  unsigned int last_u = -1;

  if (first_u <= last_u)
    printf("less than\n");
  else
    printf("greater or equal\n");

  /* defining the variables as signed */
  int first_s = 0;
  int last_s = -1;

  if (first_s <= last_s)
    printf("less than\n");
  else
    printf("greater or equal\n");

  return 0;
}

除此之外,您应在<条件中使用while,或将last的初始值定义为size-1。否则,如果您要搜索的元素大于数组中的最后一个元素,则会超出范围。

答案 2 :(得分:3)

首先,middle的负值是溢出(unsigned int)。

另外我认为你应该有:unsigned int last = size-1因为如果first等于last = size,你将使用ptrToArray [middle]和middle = size,因此它将超出数组边界。这也将解决上面提到的size = 0的情况。

最后,为了使您的代码更易于阅读,您可以编写: middle =(first+last)/2是[第一个,最后一个]空格的中间位置,equals to first+(last-first)/2

答案 3 :(得分:2)

当你在寻找一个不在数组中的元素并且比数组大时,你可能会越界,因为当lastfirst相等时,允许继续迭代while (first <= last)

想想发送空数组时会发生什么:size == 0

first = 0, last = 0,因此:(first <= last) == true
然后,middle = 0 + (0 - 0)/2 = 0,然后您访问ptrToArray[0],这是超出范围的。