zoukankan      html  css  js  c++  java
  • 垃圾代码评析——关于《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;
    }
    

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

  • 相关阅读:
    CSS Modules
    回调地狱
    css实现双色饼图
    vue项目中使用less
    pug(jade) 学习笔记
    React组件proptypes, ref
    react+express实现跨域
    react高阶组件
    Oracle数据库出现锁表情况分析
    JPA常用注解记录
  • 原文地址:https://www.cnblogs.com/pmer/p/2764854.html
Copyright © 2011-2022 走看看