AU3中BitAnd与Win32汇编中的&按位进行与操作的本质思考
本帖最后由 李岸 于 2015-1-24 19:00 编辑心越静,思考的越透彻。不要着急,宇宙有求必应!我可能是最笨的才会写出来进行思考,写出来至少自己在碰到这些本质上的问题不会再度卡壳。本着"没有交流的思考不是完整的思考"的原则,我将这篇文章发出来,如果能引发出你的共鸣,那么请像我一样。期待与你的交流!
在AU3论坛中找到了篇帖子为这个问题作为参考:
白痴问个比较白痴的问题:在实际中我到底怎么样才会用到BitOR,BitAND,BitXOR?
AU3中的BitAnd、BitOr、BitNot、BitXor、And、Or、Not;分别对应汇编中的And、Or、Not、Xor、&&、||、!;两者中的前四个指令,多用于两个操作数之间的逻辑操作,并且保存结果到变量或者源操作数中。两者中的后三个指令,多用于表达式中的逻辑操作。&&、||都会被翻译成与自身相或,来判断是否等于0.所以结果不会变只会影响相应的标志位。如ZF,程序也正是用ZF标志位来判断是否转跳。
总是觉得逻辑上过得去,但是总觉得缺少了点背景资料(为什么会有这个东西存在,它的历史是什么呢,背后的思想又是什么呢?);既然这类操作多用于组合标志位,那么不妨以此来作为思考的切入点。
一个Flg初始化为0000000000000(32个0),那么每一个都是一个"Flg",0和1表示(开或者关)。(这句话的意思是让你把思维切换到二进制来思考这个问题)
纵观整个AU3帮助文档,所有涉及组合标志位的函数如:FileOpen,WinGetState等函数(有兴趣的可以查看一下windowsconst.au3)的组合标志位都是1、2、4、8、16...发现了什么?它们与二进制每位的权值一一对应。
引申出另一个问题:为什么没有用3、5、7、9..这些常数作为组合标志位的值呢?对照一下上下的区别是:没错,上文是除了1都是偶数,下文是奇数。所以这个问题的答案可以说:用上文的所有偶数构造出最接近下文的偶数,然后+1就可以了。所以一个二进制的Flg组合标志位,十进制表示为奇数,那么这个二进制位的第0位必然是1.
从另一个角度讲,这样的组合标志位原则有利于逻辑运算;比如9 and 8,二进制位分别为1001与1000,除了8所代表的二进制第三个标志位其他位全部为0。根据与运算的规则,结果肯定不为零所以成真。
又例如一个实际的例子:
1 = 窗口存在
2 = 窗口可见
4 = 窗口可用(未被禁用)
8 = 窗口为激活状态
16 = 窗口为最小化状态
32 = 窗口为最大化状态
你想要判断这个窗口是不是最小化,就用:
$win_state=WinGetState("***","****")
If BitAND($win_state,8)==8 Then ***********
如果窗口的状态为1、2、4,那么二进制为0001,0010,0100.可见8d所代表的第三位都是0,所以If BitAND($win_state,8)==8肯定是不成立的。
如果为16和32呢?那么二进制为10000,100000。可见8d所代表的第三为都是0,所以If BitAND($win_state,8)==8肯定是不成立的。
只有16<窗口状态>8 的情况下,If BitAND($win_state,8)==8 Then ***********才会成立。因为这时候无论要表示9~15中的任意一个数都要用到8(二进制的第三位为1),但大于15就进位了。
从这个意义上讲,窗口的状态总是向下包含的;可以看到8(窗口为激活状态),绝对包含,1、2、4这些属性位。因为“窗口为激活状态”,那么不可能不存在这些状态“窗口存在”, “ 窗口可见 ”,“窗口可用(未被禁用) ”,但二进制表示为8的时候,又有了一个新的意义那就是“窗口为激活状态”。同理没有“窗口最大化”的概念,哪里来的“窗口最小化”这个概念呢?没有“窗口最小化”这个概念,哪里来的“窗口为激活状态”这个概念呢?无论从数学的意义上,还是从函数说明上来理解这个概念都是行得通的。
继续往下思考,可以发现有些标志位的组合都有类似这样的说明“此标志必须与XX标志共同使用”或者“此标志不能与XX标志共同使用”;例如OPENFILENAME这个结构中,OFN_FILEMUSTEXIST和OFN_PATHMUSTEXIST必须共同使用,那么这两个常量的取值是多少呢?分别是1000h和800h;
总结:
先把视角切换到二进制位的32位Flg,帮助文档上缩写的十进制1、2、4、8,说白了只是标志位组合中的相应位是否为1而已。(为了适应人类的长了十根手指而产生的思考局限)
再说的透彻点,这个组合标志位所代表的十进制,或者十六进制的数值是没有意义的,从二进制的角度来讲它也只代表32个按钮的开关状态而已。
强制开启开关可以使用or 开关组状态1和索引(我觉得这样理解更透彻),如果要检测一个开关是否被开启可以使用and 开关组 索引和状态1。
如果把组合标志位想像成开关,1代表开,0代表关。将BitAnd(32个开关,000000000001000)1代表我要开其中的一个开关。如果这个开关之前是关着的,那么 1 and 0 = 0 。
如果这个开关之前是开着的,那么1 and 1 = 1。可见and指令是返回之前开关的状态...
按照这个思路的话,如果我要关一个开关,这个开关之前是关着的,0 and 0 = 0 反之 0 and 1 == 0,“and指令是返回之前开关的状态”在这里又不适用了。 欢迎拍砖~{:face (411):} 不錯,慢慢消化. 感谢楼主分享,感觉还不错 正好,慢慢来,学习
页:
[1]