幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
12
返回列表 发新帖
楼主: secondsen

+= 和 a = a + 1 还是不一样的嘛 ^_^

[复制链接]

0

主题

8

帖子

84

积分

②入门

积分
84
发表于 2008-4-8 03:00:24 | 显示全部楼层
你的b好像沒有用到呀??

把b刪掉...
________________________
a = Time.now
p Time.now - a
a = Time.now
p Time.now - a

结果不一样啊。。。。
a = Time.now
p Time.now - a
a = Time.now
p Time.now - a

结果就差不多阿。。。。。

这样子。是怎么个样子
__________________________

你寫的東西一模一樣...
我應該沒有誤解.....
回复 支持 反对

使用道具 举报

0

主题

4

帖子

37

积分

②入门

积分
37
发表于 2008-5-2 21:36:08 | 显示全部楼层
终于看懂LZ的脚本了........(新人jiong )8过何必钻这样地牛角尖捏?
回复 支持 反对

使用道具 举报

3

主题

18

帖子

188

积分

③业余

积分
188
发表于 2008-5-26 10:32:44 | 显示全部楼层
引用第8楼nightaway于2008-03-12 21:33发表的  :
a+=1   编译后的汇编指令  add
a++     编译后的汇编指令  inc
inc 的运算周期 小于 add 所以 a++ 比 a+=1 快

如果楼主有疑问可以学学汇编语言.. 这样你的编码水平会大增..

回答正确,+= 比 =    +    效率要高很多,特别是在早期的计算机上
####################
a=a+1
MOV  EAX,A
MOV  EBX,1
ADD  EAX,EBX
MOV  A,EAX
##################
a+=1
MOV  EAX,A
INC   EAX
MOV  A,EAX
####################
如果没记错的话应该是这样计算的
回复 支持 反对

使用道具 举报

550

主题

9117

帖子

214748万

积分

超级版主

如同神一般的存在,腿神!拖后腿的神~~

Rank: 8Rank: 8

积分
2147483647
 楼主| 发表于 2008-5-31 17:11:32 | 显示全部楼层
这楼什么时候这么高了。。。谢谢前面  解释的非常明白的两位。。。

也很感谢不懂的人来捧场  
我就是你们的神,庶民们,追随我吧!跟着我一起拖后腿!
回复 支持 反对

使用道具 举报

8

主题

215

帖子

2223

积分

⑥精研

积分
2223
发表于 2008-6-12 06:34:24 | 显示全部楼层
引用第8楼nightaway于2008-03-12 21:33发表的  :
a+=1   编译后的汇编指令  add
a++     编译后的汇编指令  inc
inc 的运算周期 小于 add 所以 a++ 比 a+=1 快

如果楼主有疑问可以学学汇编语言.. 这样你的编码水平会大增..
引用第12楼jiangcq于2008-05-26 10:32发表的  :
回答正确,+= 比 =    +    效率要高很多,特别是在早期的计算机上
####################
a=a+1
MOV  EAX,A
MOV  EBX,1
ADD  EAX,EBX
MOV  A,EAX
##################
a+=1
MOV  EAX,A
INC  EAX
MOV  A,EAX
####################
如果没记错的话应该是这样计算的
这个……事情要具体问题具体分析对吧,张冠李戴就不太好了 ^ ^
更详细的论述发在这里了:http://rednaxelafx.javaeye.com/blog/202334

+=之类的复合赋值运算符在许多语言都有,语义类似但是实现的方式并不总相同。
RGSS里的脚本语言是Ruby,RPG Maker VX里使用的Ruby是1.8.1版的MRI。Ruby源代码并没有被直接编译到机器码,而是被Ruby解释器所解释:先把源代码翻译成抽象语法树,然后解释抽象语法树。
在Ruby里,一切皆是对象。因此像是加号减号之类的运算,也被看作是对象上的方法。a += 1的语义是a = a.+(1)(语义是:调用a对象上的+()方法,把1作为参数传进去,然后将方法的返回值赋值给a)。
+=的语义不是单独定义,而是由+()方法所决定的;换句话说一个类定义了+()方法就自动具备了+=。假如有语句a = 1,那么a是一个Fixnum,+=当中调用的+()方法就是Fixnum#+()。

先看看+=被解析器识别为什么了。Ruby的扫描器(词法分析器)里有这么一段:
  1. case '+':
  2. c = nextc();
  3. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  4.     lex_state = EXPR_ARG;
  5.     if (c == '@') {
  6.         return tUPLUS;
  7.     }
  8.     pushback(c);
  9.     return '+';
  10. }
  11. if (c == '=') {
  12.     yylval.id = '+';      // 注意这里,id是'+'
  13.     lex_state = EXPR_BEG;
  14.     return tOP_ASGN;      // 然后整体以tOP_ASGN返回
  15. }
复制代码
可以看到+=被识别为tOP_ASGN类型的token。

a += 1形式的语句对应的这条语法:
  1. statement: //...
  2.     | var_lhs tOP_ASGN command_call
  3.     // ...
  4.     | //...
  5.     ;
复制代码
语法对应着解析器,而解析器会生成抽象语法树。如果等号前的是||则语法生成NODE_OP_ASGN_OR节点,如果是&&则生成NODE_OP_ASGN_AND节点,其它则调用call_op()函数生成NODE_CALL节点。
  1. var_lhs tOP_ASGN command_call
  2. {
  3.     value_expr($3);
  4.     if ($1) {
  5.         ID vid = $1->nd_vid;
  6.         if ($2 == tOROP) {
  7.             $1->nd_value = $3;
  8.             $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
  9.             if (is_asgn_or_id(vid)) {
  10.                 $$->nd_aid = vid;
  11.             }
  12.         }
  13.         else if ($2 == tANDOP) {
  14.             $1->nd_value = $3;
  15.             $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
  16.         }
  17.         else {
  18.             $$ = $1;                                       // 获得var_lhs对应的节点
  19.             $$->nd_value = call_op(gettable(vid),$2,1,$3); // 这里,call_op将返回一个NODE_CALL节点,
  20.                                                            // 并赋值给var_lhs对应节点的“值”
  21.         }
  22.     }
  23.     else {
  24.         $$ = 0;
  25.     }
  26. }
复制代码
由于节点的“值”(nd_value)被赋值为一个NODE_CALL节点,这里实质上完成了将a += 1变为a = a.+(1)的转换。

看看a = a + 1对应的语法和动作:
  1. lhs '=' command_call
  2. {
  3.     $$ = node_assign($1, $3);
  4. }
复制代码
结合下面node_assign()函数的实现,可以看到这里是把右手边的节点赋值给了左手边节点的“值”(nd_value)。并且,右手边的a + 1对应的语法与动作如下:
  1. arg '+' arg
  2. {
  3.     $$ = call_op($1, '+', 1, $3);
  4. }
复制代码
也是调用call_op()生成NODE_CALL节点,跟前面a += 1时一样。
于是,a += 1与a = a + 1在被解析后所生成的语法树是一样的,后续执行中就都是等价的了。
  1. static NODE*
  2. node_assign(lhs, rhs)
  3.     NODE *lhs, *rhs;
  4. {
  5.     if (!lhs) return 0;
  6.     value_expr(rhs);
  7.     switch (nd_type(lhs)) {
  8.       case NODE_GASGN:
  9.       case NODE_IASGN:
  10.       case NODE_LASGN:
  11.       case NODE_DASGN:
  12.       case NODE_DASGN_CURR:
  13.       case NODE_MASGN:
  14.       case NODE_CDECL:
  15.       case NODE_CVDECL:
  16.       case NODE_CVASGN:
  17.         lhs->nd_value = rhs; // 注意这里
  18.         break;
  19.       case NODE_ATTRASGN:
  20.       case NODE_CALL:
  21.         lhs->nd_args = arg_add(lhs->nd_args, rhs);
  22.         break;
  23.       default:
  24.         /* should not happen */
  25.         break;
  26.     }
  27.     return lhs;
  28. }
复制代码


这是Fixnum#+()对应的C函数:
  1. /*
  2. * call-seq:
  3. *   fix + numeric   =>  numeric_result
  4. *
  5. * Performs addition: the class of the resulting object depends on
  6. * the class of <code>numeric</code> and on the magnitude of the
  7. * result.
  8. */
  9. static VALUE
  10. fix_plus(x, y)
  11.     VALUE x, y;
  12. {
  13.     if (FIXNUM_P(y)) {
  14.     long a, b, c;
  15.     VALUE r;
  16.     a = FIX2LONG(x);
  17.     b = FIX2LONG(y);
  18.     c = a + b;
  19.     r = LONG2NUM(c);
  20.     return r;
  21.     }
  22.     if (TYPE(y) == T_FLOAT) {
  23.     return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
  24.     }
  25.     return rb_num_coerce_bin(x, y);
  26. }
复制代码
该函数被注册到Ruby的类型系统中:
  1. rb_define_method(rb_cFixnum, "+", fix_plus, 1);
复制代码
rb_cFixnum是继承自rb_cInteger的类:
  1. rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
复制代码
上面rb_define_method函数使得fix_plus与一个NODE_CFUNC关联在了一起。这个函数会调用rb_intern(name)来将方法名转换为ID,这里对运算符做了特殊处理:
  1. if (name[0] != &#39;_&#39; && ISASCII(name[0]) && !ISALNUM(name[0])) {
  2.     /* operators */
  3.     int i;
  4.     for (i=0; op_tbl[i].token; i++) {
  5.         if (*op_tbl[i].name == *name &&
  6.             strcmp(op_tbl[i].name, name) == 0) {
  7.             id = op_tbl[i].token;
  8.             goto id_regist;
  9.         }
  10.     }
  11. }
复制代码
这个特殊处理可以保证运算符与内建函数的对应关系。
回复 支持 反对

使用道具 举报

550

主题

9117

帖子

214748万

积分

超级版主

如同神一般的存在,腿神!拖后腿的神~~

Rank: 8Rank: 8

积分
2147483647
 楼主| 发表于 2008-6-12 08:01:45 | 显示全部楼层
要。。要收起来  多看看。。。
我就是你们的神,庶民们,追随我吧!跟着我一起拖后腿!
回复 支持 反对

使用道具 举报

0

主题

47

帖子

376

积分

④见习

积分
376
QQ
发表于 2008-8-18 13:35:10 | 显示全部楼层
周期啊
感激你让我拥有秋天的美丽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2025-6-20 03:11 , Processed in 0.013306 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表