垃圾代码评析——关于《C程序设计伴侣》6.3.7

【样本】

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p116

【评析】

  作者认为“截取字符串”也是“常见的字符串处理任务”是武断的。C语言函数库中并不需要这样的函数,因为这种操作并非是对字符串的一个基本操作。

【样本】

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p116

【评析】

  这里对函数参数的分析虽然不能说有错,但却因为不够彻底而臃余。因为描述源字符串中的一段,应该只需要2个参数就足够了。例如,如果要说明"ABCDE"中的第2个字符开始3个字符,并不需要"ABCDE",2和3这三个实参,"ABCDE"+(2-1) 和 3就足够了。

【样本】

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p116

【评析】

   这个函数的参数很怪异。首先pos、n都是对source的进一步明确,但却被dest这个参数割裂开来;其次,习惯上C语言函数约定俗成的习惯是把dest放在前面,把描述source的参数放在后面。但这个函数却违背了业界共同遵守的公序良俗。

   函数内部的

for( int i=0 ; i < n ; ++i )

{

   dest[i] = source[pos+i];

}

的问题是,根本就没有考虑到在source的第pos~第pos+n-1个字符中存在\0的情形。既然是拷贝字符串,遇到\0则应该终止。但这个函数却不是这样,遇到\0它会固执地继续copy下去,直到copy完n个字符为止,哪怕有些是没用的不需要copy的。这不但降低了程序性能,在有些情况下还是一种UB错误。例如如下调用就存在这种错误:

strsub("ABC",dest,0,5);

  错误在于会访问到"ABC"范围之外,在C语言中这是一种Undefined behavior。

  这个函数的正确写法应该是:

void strsub( char *dest , char *source , int n )
{
   while( n -- > 0)
      if( ( *dest ++ = *source ++ ) == '\0' )
         return ;

   *dest = '\0';   
}

 【样本】

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p116~117

【评析】

  很遗憾,作者想到了使用memcpy(),却没注意到memcpy()只用了三个参数,这已经足以说明strsub()参数设计上的画蛇添足了。

  此外,使用memcpy()依然存在copy多余字符的低效行为以及越界访问的错误。

【样本】

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p117

【评析】

  正如前面分析所指出的那样,两个strsub()都是错误的。即使抛开这点不谈,说第二个写法效率高于第一个写法也是毫无根据的。此外C语言程序也并非永远把性能作为追求的目标。

  作者的这两个strsub()其实都不“简单”,因为压根用不着写这种strsub()函数。strsub()的功能通过简单的一次函数调用就能实现:

strncpy(dest,source+pos,n);

 【样本】

 

   ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p117

【评析】

  这个测试及后面长篇大论的说明非常搞笑,而且非常令人费解。

  首先,作者没有考虑strstr(suorce,begin)返回值为NULL的可能性。此时程序会发生一个严重的错误(strlen(ppos)调用没有意义)。

  其次,如果strstr(suorce,begin)返回值不为NULL,那么main()所做的事情无非是

#include <stdio.h>
#include <string.h>
int main( void )
{
  char *begin = "live";
  char substr[256];
  strcpy(substr,begin);
  puts(substr);
  return 0;
}

 而已。其余神马的全是浮云。

 

posted @ 2012-11-11 18:42  garbageMan  阅读(2025)  评论(2编辑  收藏  举报