1
icylogic 2014-04-11 11:21:17 +08:00 via Android
我觉得你是没搞清变量和常量的区别。。。
|
3
icylogic 2014-04-11 11:29:22 +08:00 via Android
@GPU 3是常量,#define M 3 那m也是常量,但int a=3 a就是变量,所以你的问题其实是为什么不用变量用常量
|
6
icylogic 2014-04-11 11:31:42 +08:00 via Android
准确的说是常量表达式
|
7
jsonline 2014-04-11 11:34:03 +08:00 1
关于 Magic number
http://coolshell.cn/articles/4576.html |
8
xia0ta0 2014-04-11 11:34:31 +08:00
幻数就是一般的数字,但是这个数字是有特定含义的,比如:
你写 int testNum = 3.14; 别人可能不是到是干啥的,你最好这样写 #define PI 3.14 float testNum = PI; 别人就知道你这是在测试圆周率,如果以后你要测得更精确,可以改一下: #define PI 3.14159 define PI 3.14 与const float pi = 3.14;的区别就是编译之前,编译器会将所有代码有PI的地方替换成3.14,而pi只是一个变量(常量,不能修改),会编译到二进制文件中。 |
9
jsonline 2014-04-11 11:35:19 +08:00
引文:
不过,没过一会,发现了一个bug,经过大家的调查(2.6.38版没有发现这个问题),很快,找到了原因,是因为一个内存地址的问题,一个叫Yinghai Lu的人(看其名字应该是中国人,其邮件是@kernel.org)找到了原因—— radeon card使用了一个不正确的内存地址[0xa0000000 - 0xc000000]。Joerg Roedel跟贴说,这个地址超出了4GB的内存,然后他和Alex Deucher聊了一会,觉得不应该是这个问题,因为这个地址应该是GPU的,而不是系统内存的。 好像,Yinghai Lu没有理会他们说的不应该是这个问题,给出了个fix: 看到这个fix,Linus Torvalds不高兴了,他回贴问道: 为什么全都是Magic Numbers? 为什么0×80000000就那么特殊? 为什么我们这样改就行? 还说了这样一句话—— This kind of “I broke things, so now I will jiggle things randomly until they unbreak” is not acceptable. 这种“我把事搞砸了,就随意地调整直到事情又工作”的方式是不可接受的。 还说,这里即没有说明为什么我们fix在了正确的地方(也没有解释那些Magic Number是什么),也没有回滚那个有问题的patch。还说—— Don’t just make random changes. There really are only two acceptable models of development: “think and analyze” or “years and years of testing on thousands of machines”. Those two really do work. 不要乱改。那里只有两个可行的开发模式:“思考和分析” 或是 “数年数年地不断地在几千台机器上测试”。这两个方式才是真正可行的。 当然,Yinghai Lu对其做了解释,说我们的确调查过了,老的代码用的内存地址是0×80000000,新的则是用0xa0000000,而0xa0000000不工作。这又引发了 Linus Torvalds 的不满的回贴。Linus说—— |
10
jsonline 2014-04-11 11:37:30 +08:00
Magic Number 最大的问题是:
为什么是这个 number,不是另一个 number 呢? 如果有一天需求变更了,这个 number 还适用吗? 所以 Magic Number 看起来就像 Magic 一样,无法琢磨! |
11
jsonline 2014-04-11 11:40:37 +08:00
Linus 大神每一次骂人我都看得好爽啊!
|
12
zhujinliang 2014-04-11 11:41:26 +08:00 1
幻数 有多层含义
1. 在代码中使用的常量,如果没有给出说明,而且他人难以推测如何得出的这个数,那就称作幻数 2. 随意指定的值,一般该值的多少对程序没有太大影响,比如 MD5 等哈希算法中的初始因子 3. 一个数值,如果得出它需要复杂的科学计算,或者通过穷举等试验得出的,可以直接写上,然后旁边写一个注释,意思是这个你不必深究了 例如: setTimeout(fn, 86400) // 这个86400我认为是幻数,你不能一眼就知道这个指令想做什么 更好的写法是 setTimeout(fn, 24*60*60) // 一看就知道是延时一天 |
13
jsonline 2014-04-11 11:43:25 +08:00
使用常量是为了不让别人(和自己修改),所以 PI 不能作为变量来声明。这跟 Magic Number 无关。
|
14
slixurd 2014-04-11 11:51:42 +08:00
把Magic Number用在大型工程中不可取,define其实也不太好
Effective C++条款3 如果用define可能导致记号未被编译器看见,从而无法获取到编译错误信息指向的信号,只有一个Magic Number,包括调试当中,无法用记号来检索 另外用常量可能比define生成更小的代码 |
16
mrsatangel 2014-04-11 12:00:44 +08:00 via iPhone
从汇编来看,就是内存操作数和立即数的区别,操作两者占用的总线周期是不一样的。当然如果不是大规模使用变量代替常量,区别可以忽略。另外赞同前面有人讲的,实践中最大的因素是c只支持常量长度的数组,不然只有动态分配。
|
17
ETiV 2014-04-11 12:05:00 +08:00
变量: 运行时可以对他进行处理的数值. 数字上来讲, 就是加减乘除.
"变量名"只是编程语言里一种对于变量的引用. 当然变量名是给人看的. 所以需要简单易懂, 望文生义. 常量: 运行时不可变而且一定不能变的量. 所以就需要对他进行保护, 以避免代码上产生的漏洞, 对"常量"进行修改. 后半句就解释了, "为什么都可以起名字, 但还非要区分变量常量"的问题. |
19
xia0ta0 2014-04-11 12:18:59 +08:00
使用上,符号常量用PI 和常变量用pi;程序执行效率上肯定是符号常量快,因为它只是一个立即数;变常量还要操作内存。
使用变常量还是符合常量主要是从原理上考虑,如果你想把这个常量编译到程序中,就用变常量;如果只是作为一个便于记录和辨识的符合,不需要编译到二进制文件,就用符合变量。 当然,符号变量的宏定义还有很多强大的功能。 |
20
xia0ta0 2014-04-11 12:20:54 +08:00
一般习惯用大写表示符号常量,常变量用小写。
|
21
GPU OP @xia0ta0 啊, 我终于明白原因了. !!! . 你这个解释终于能令我这个初学者明白啦 .
书本上要提到这个东西是因为 , 他上一个题目是说 for语句的. 但是他是直接用了"幻数"直接放在for语句里面的条件 . 然后他下一篇就立马提到 "符号常量" 意思就是把这些"幻数"定义一下 , 这样当程序被作者以外的人看,也可以明白这个"幻数"是做什么用的. 再然后 , 劈开你说的"宏定义" 这些强大的功能 ,那么这个符号常量是没有用途的 ,只是让人看代码时更容易明白代码的意思 , 而书上要提到这个东西 , 意义就是让程序员们能良好的编写代码的习惯.! . 就想到这么多了. |
23
lukic 2014-04-11 13:17:39 +08:00
既然楼主是初学者就没必要纠结这么多,多实践就慢慢明白了。
|
25
GPU OP @xia0ta0 《c程序语言设计》 是不是那本K&R? . 徐宝文 先生 译著的. 我现在就是看这个本 .发的现在这个问题 . 只是就像#16 说的那样我自己纠结而已. 总是把问题想得太复杂,非要弄懂他不可 这样子.
|
26
xia0ta0 2014-04-11 13:41:31 +08:00
好吧,且读且珍惜。。。。
|
27
levie 2014-04-11 16:08:52 +08:00
我理解啊,lz不是要弄清楚常量和变量,而是什么样的数是幻数,以及我们为什么要避免使用幻数。
比如 int height = (2 + 100 + 5) * 2; 这里面2、100、5、2都是幻数,一般人读到这行代码都会困惑这些数怎么来的,所以也有称它们是神仙数的,只有神仙才能猜到那些数是什么意思。 如果改成这样写: int topMargin = 2, contentHeight = 100, bottomMargin = 5, scale = 2; int height = (topMargin + contentHeight + bottomMargin) * scale; 这样的代码就好读了,当然写起来也累_(:з」∠)_ 另外一个好处是改参数的时候容易,比如你要把改缩放比例从2为3,那么你只要改scale = 3就好了,而不用查找所有2,然后费劲地把其中一部分2改成3. 所以,幻数与否于不是看常量变量。 |