零缺陷编程读书笔记(七)自己设计并使用断言(5)

来源:互联网 发布:证书打印软件 编辑:程序博客网 时间:2024/04/29 19:23

8 你又做假定了吗?

有时在编程序时,有必要对程序的运行环境做出某些假定。但这并不是说在编程序时,

总要对运行环境做出假定。

1

/* memset ───  byte的值填充内存  */

void* memset(void* pv,byte b, size_t size)

{

 byte* pb = (byte*)pv;

 while(size-- > 0)

  *pb++ = b;

 return(pv);

}

 

2

/* longfill ───  long的值填充内存块在填完了最后一个长字之后

 *  返回一个指向所填第一个长字的指针

*/

long* longfill(long* pl, long l, size_t size);    /* 原型  */

memset(void* pv, byte b, size_t size)

{

 byte* pb = (byte*)pv;

 if(size >= sizeThreshold)

{

 unsigned long l;

 l = (b<<8) | b;    /*  4个字节拼成一个长字  */

 l = (l<<16) | l;

 pb = (byte*)longfill((long*)pb, l, size/4);

 size = size%4;

}

 while(size-- > 0)

  *pb++ = b;

 return(pv);

}

 

sizeThreshold进行测试是为了使memset只有在用 long进行填充速度更快时才进行相应的填充。否则就仍用 byte进行填充。

 

这个 memset新版本的唯一问题是它对编译程序和操作系统都做了一些假定。例如这段代码很明显地假定 long占用四个内存字节,该字节的宽度是八位。

 

3

某些程序员“改进”这一程序的方法,是把它写成下面这种可移植性更好的形式:

memset(void* pv, byte b, size_t size)

{

 byte* pb = (byte*)pv;

 if(size >= sizeThreshold)

{

 unsigned long l;

 size_t sizeSize;

 l = 0;

 for(sizeSize=sizeof(long); sizeSize-->0; NULL)

 l = (l<<CHAR_BIT) | b;

 pb = (byte*)longfill((long*)pb, l, size/sizeof(long));

size = size%sizeof(long);

}

 while(size-- > 0)

  *pb++ = b;

 return(pv);

}

由于在程序中大量使用了运算符 sizeof,这个程序看起来移植性更好,但“看起来”不等于“就是”。如果要把它移到新的环境中还是要对其进行考察才行。

 

4

至于对程序中所做的其他假定,可以利用断言和条件编译进行相应的验证:

memset(void* pv, byte b, size_t size)

{

 byte* pb = (byte*)pv;

 #ifdef MC680x0

 if(size >= sizeThreshold)

{

 unsigned long l;

 ASSERT(sizeof(long)==4 && CHAR_BIT==8);

 ASSERT(sizeThreshold>=3);

 /*  用字节进行填充直到对齐在长字边界上  */

 while( ((unsigned long)pb & 3) != 0 )

{

  *pb++ = b;

size--;

}

 /*  现在拼装长字并用长字填充其他内存单元  */

 l = (b<<8) | b;    /*  4个字节拼成一个长字  */

 l = (l<<16) | l;

 pb = (byte*)longfill((long*)pb, l, size/4);

 size = size%4;

}

#endif  /* MC680x0 */

 while(size-- > 0)

  *pb++ = b;

 return(pv);

}

 

 

消除所做的隐式假定或者利用断言检查其正确性

 

9 光承认编译程序还不够

最近Microsoft的一些小组渐渐发现他们不得不对其代码进行重新的考察和整理,因为相当多的代码中充满了“+2”而不是“+sizeof(int)”、与 0xFFFF而不是 UINT_MAX 进行无符号数的比较、在数据结构中使用的是 int而不是真正想用的 16位数据类型这一类问题。

 

为了在 Intel  80386和更新的处理器上生成更快更小的程序,编译程序组改变了 int

大小(以及其他一些方面)。虽然编译程序组并不想使公司内部的代码垮掉,但是保持在市场上的竞争地位显然更重要。毕竟,这是那些自己做了错误假定的 Microsoft程序员的过错。

 

转载请注明原创连接:http://blog.csdn.net/wujunokay/article/details/17802175

 

 

 

87 0
原创粉丝点击