昨天一个朋友拿来了他自己改写的一段C语言程序,是使用指针改写了二分查找的算法,可他编译怎么也过不了,于是让我来看看,我在教室看时也没发现什么问题,程序代码如下:

  1. #include <stdio.h> 
  2.  
  3. int *bsearch(int *t, int n, int x)  
  4. {  
  5.     int *l = t, *h = t + n, *mid;  
  6.     while (l < h) {  
  7.         mid = (l + h) >> 1;  
  8.         if (x < *mid)  
  9.             h = mid;  
  10.         else if (x > *mid)  
  11.             l = mid + 1;  
  12.         else  
  13.             return mid;  
  14.     }  
  15.     return NULL;  
  16.  
  17. int main(void)  
  18. {  
  19.     int *result;  
  20.     int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  21.     result = bsearch(data, 10, 2);  
  22.     if (NULL != result)  
  23.         printf("%d\n", *result);  
  24.     return 0;  

我决定等回寝室后上机跑跑。有兴趣的朋友也可以自己试下,先不要看我下面的调试结果自己跑跑~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

我上机一跑,发现提示错误如下:

F:\Program Files\CodeBlocks\project\point\main.c||In function `bsearch':
F:\Program Files\CodeBlocks\project\point\main.c|7|error: invalid operands to binary +

=== Build finished: 1 errors, 0 warnings ===

定位到如下行:

mid = (l + h) >> 1;

这是为什么呢?这行操作不就是求最大值和最小值间的范围吗!有什么问题呢?mid,l,h分别是三个×××指针,指向中间值,最小值,最大值,又移一位的操作也就等同于除2的操作,看起来天衣无缝啊!再看提示信息给出的是“invalid operands to binary +”,加号有什么问题吗?我们仔细想想,l 指针加上h指针有什么问题吗?对哦!两个指针能够相加吗?相加的结果是什么呢?C语言中规定两个指针是不能进行加运算的,所以这个地方编译通不过了。哈哈!找到问题的出处就好解决了。既然无法进行加,那就干脆减呗!于是我修改了那行代码:

mid = l + ((h - l) >> 1);

终于程序能够正常运行了,C语言中指针的特性确实可以让我们把程序写的出神入化,但也带来了不小的问题,难怪面向对象的java语言就屏蔽了指针的操作。大家共勉~~

虽然这个程序他没调出来,不过他给我看了一个非常精彩的断言宏的定义,分享给大家:

#define assert(e) ((void)((e) || _assert_error(__FILE__, __LINE__)))

他利用了||运算符的顺序求值的特性,如果e为真就直接返回了,如果e为假才打印出断言信息。我觉得写的非常简炼~~以前我写断言宏的时候都比这个复杂,不知道大家还有没有更加简炼的写法,抛砖引玉了~~