魔数(magic number)

本文探讨了程序设计中直接使用数字(魔数)的问题,分析其对代码可读性和可维护性的负面影响,并通过示例展示了如何利用宏定义或常量来改善这些问题。

 

魔数(magic number),即在编写程序时直接在程序中运用数字,而不是采用定义宏或是const变量的方式,图1是使用了魔数的一个示例程序。其中的64是指Msk的最大字节数。从这一程序中可以看出,Msk的最小字节数是MIN_MSK_LEN,即20。采用魔数的危害有:
    1) 降低了程序的可读性。有人可能会提出,那加一些注释不就完了吗?如果真是采用加注释的方式,那为什么不将其定义成一个宏或是const常量呢?要知道查看注释的效率肯定没有直接看代码来得快和方便,也不存在不同步的问题(代码与注释有可能不同步)。
    2) 如果下一次这个最大值要从64改为128,那得在adjustMask()中对每一处都进行更改。另外,当一个项目较大时,魔数的存在会使得程序维护非常、非常困难。

由此看来,这里的“魔”不应理解成象“魔法(magic)”那样神奇,而应理解为象“魔鬼(monster)”那样可怕。

 

[cpp] view plain copy

 print?

  1. 00290: #define MIN_MSK_LEN 20  
  2. 00291:  
  3. 00292: int adjustMsk (MskContext* Context)  
  4. 00293: {  
  5. 00294:     char temp [64] = {0};  
  6. 00295:  
  7. 00296:     if (Context->lenMsk > 64) {  
  8. 00297:         memcpy (temp, Context->msk + (Context->lenMsk - 64),    64);  
  9. 00298:         ...  
  10. 00399:         memcpy (Context->msk, temp, 64);  
  11. 00300:     }  
  12. 00301:     else if (Context->lenMsk < MIN_MSK_LEN) {  
  13. 00302:         return ERROR;  
  14. 00303:     }  
  15. 00304:     ...  
  16. 00305: }  


采用宏之后的版本。其中定义了MAX_MSK_LEN的大小为64,如果其它函数中也需要用到Msk的最大值,那么也可以引用这一宏。如果下一次想将最大值从64改为128时,只要改MAX_MSK_LEN宏的定义就行了。另外,这种宏定义的存在有利于模块与模块之间共享,从而在一定程度上提高重用性。

 

 

[cpp] view plain copy

 print?

  1. 00289: #define MIN_MSK_LEN 20  
  2. 00290: #define MAX_MSK_LEN 64  
  3. 00291:  
  4. 00292: int adjustMsk (MskContext* Context)  
  5. 00293: {  
  6. 00294:     char temp [MAX_MSK_LEN] = {0};  
  7. 00295:  
  8. 00296:     if (Context->lenMsk > MAX_MSK_LEN) {  
  9. 00297:         memcpy (temp, Context->msk + (Context->lenMsk - MAX_MSK_LEN),  
  10. 00298:             MAX_MSK_LEN);  
  11. 00399:         ...  
  12. 00300:         memcpy (Context->msk, temp, MAX_MSK_LEN);  
  13. 00301:     }  
  14. 00302:     else if (Context->lenMsk < MIN_MSK_LEN) {  
  15. 00303:         return ERROR;  
  16. 00304:     }  
  17. 00305:     ...  
  18. 00306: }  

 

[cpp] view plain copy

 print?

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. int main( void )  
  5. {  
  6.     //我们经常会看到这样的程序: 本程序中有两个魔数0和10,  
  7.   
  8.     //它的意义在上下文中没有体现出来,好像这两个数是从魔术搬地从空中出现。  
  9.   
  10.     //当然程序小的时候没有这样的感觉,当程序变大之后,  
  11.   
  12.     //会发现这种行为严重影响程序的可读性(突然出现一个数字,让人难以理解)  
  13.   
  14.     //和可维护性(如:10在程序中多次出现时,维护过程中若要修改这个值时,  
  15.   
  16.     //所有出现10的地方都要被修改,增加了修改时出错的机会和工作量)。   
  17.   
  18.     for (int i=0; i<10; ++i)  
  19.     {  
  20.         cout << i << " ";  
  21.     }  
  22.       
  23.     //======================================================  
  24.   
  25.     //因此,可以参考这样写:   
  26.   
  27.     const int LOOP_BEGIN = 0; //循环的初值   
  28.   
  29.     const int LOOP_UPPER_BOUND = 10; //循环的上界  
  30.   
  31.       
  32.     for (int i=LOOP_BEGIN; i<LOOP_UPPER_BOUND; ++i)  
  33.     {  
  34.         cout << i << " ";  
  35.     }  
  36.     //======================================================  
  37.   
  38.       
  39.     system( "PAUSE" );  
  40.     return EXIT_SUCCESS;  
  41. }  

转载于:https://my.oschina.net/lCQ3FC3/blog/758929

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值