cclang2009 发表于 2011-12-22 08:54

E_ALL & ~E_NOTICE 与 E_ALL ^ E_NOTICE

<div class="entry-content">
                                                <p>在某个论坛上发现了三年前的有趣话题, 哈哈哈哈哈哈, 希望它们看过"数据结构"教科书,也许它们上学时有这本, 也许它们至今还珍藏并且从未看过</p>
<p>我觉得这话题, 的确会有一部分人会理解, 但是我希望给不理解的那部分人看的, 也许这问题本身就很粗浅, 但是我们都高估了计算机专业科班出身的那群孩子的专业知识</p>
<p>error_reporting(E_ALL &amp; ~E_NOTICE);<br>
error_reporting(E_ALL ^ E_NOTICE);</p>
<p>要理解这个问题, 得从位运算的基础说起</p>
<p>PHP中, 整形为32个位, 换句话说,</p>
1 = 00000000000000000000000000000001<br>~1 = 11111111111111111111111111111110
<p>其实对于 E_NOTICE 使用 &amp; ~ 或者 ^ 的结果, 出现问题的几率是0, 因为 E_NOTICE 的确是包含在 E_ALL 中<br>
那我们换个常量来用看看, E_STRICT 在 PHP 5.0 中被定义, 而它的特殊性, 导致它并没有被定义在 E_ALL 中,</p>
<p>假设某个童鞋写了一个程序, 而我们的程序作者同学对 E_STRICT 不包含在 E_ALL 中并不知情<br>
error_reporting(E_ALL ^ E_STRICT);<br>
这时问题就出现了, 假定当前PHP版本为5.2, 这时</p>
E_ALL    = 6143 = 00000000000000000001<span style="color: rgb(255, 0, 0);"><span style="text-decoration: underline;">0</span></span>11111111111<br>E_STRICT = 2048 = 00000000000000000000<span style="text-decoration: underline;"><span style="color: rgb(255, 0, 0);">1</span></span>00000000000
<p>这里可以看出来, 6143的第12位为0, 而2048为1,<br>
<span style="color: rgb(102, 102, 153);">###########################################</span><br>
我们来说^是什么, ^的作用是: 当 操作数A 和 操作数B 中当前位不同时, 返回结果的当前位设为1, 反过来理解就是, 当 A或B 中当前位相同时, 返回的结果的当前位为0</p>
<p>而我们的作者童鞋正是希望它的反向结果,也就是由于A/B中当前位相同,所以得到0,相当于去掉这个2048,事与愿违的是,,</p>
<p>由于6143中不包含2048, 所以6143和2048的每一位都不同, 所以我们的6143被填上了第12位的1, 变成了8191, 而不是预期的去掉第12位的1, 而作者的意图很明显的是希望去掉它, 很遗憾的是作者并不知道它本来就不在其中<br>
程序运行的结果就是所有的E_STRICT错误被展示给所有访问者欣赏<br>
<span style="color: rgb(102, 102, 153);">###########################################</span><br>
那么我们再看 &amp; ~的结果<br>
首先说, &amp;的含义是 将 A 和 B 中当前位都为1的位设为1, 反过来就是 A 或 B 中任意一个的当前位不为1, 当前位的结果都是 0<br>
而~的含义是将操作数种所有的位翻转过来, 以前是1的变成0, 以前是0的变成1, 所以:</p>
~2048 = 11111111111111111111<span style="color: rgb(255, 0, 0);"><span style="text-decoration: underline;">0</span></span>11111111111
<p>那么接下来由于 6143 的第12位为0, 被翻转的2048中第12位也为0, 而 &amp; 只有在 A 和 B
的当前位皆为1时才将结果范围为1,其他皆为0, 那么第12位仍然保持0, 其他位不同的为0, 此时~2048中除第12位其他皆为1,
在6143中原有的为1的位保持不变,其他不同的变成了0,得到的结果仍然是6143<br>
<span style="color: rgb(102, 102, 153);">###########################################</span><br>
至此我们得到一个结论</p>
<p>使用 A^B 希望将B排除在外, 希望这个条件成立, 只有在A中绝对包含B的情况下才能实现,而A中不包含B的情况下,相当于A加上B, 也就是说 ^ 在A中有B时去掉B,在A中没有B时加上B,是这么个作用</p>
<p>而使用 A&amp;~B可以在无论是否已知A中是否包含B的情况下都可以无条件的让结果中不包含B, 等于说安全的从A中去掉B<br>
<span style="color: rgb(102, 102, 153);">###########################################</span><br>
捎带介绍下 | , 它的作用是 A 和 B 中任意一个当前位为1的情况下, 结果的当前位即为1 , 这相当于 无论中 A中是否存在B, 都可以安全的添加B,不会让结果溢出<br>
<span style="color: rgb(102, 102, 153);">###########################################</span><br>
简易理解方式:</p>
使用 A ^ B: A中有B就去掉, A中没有B就加上<br>使用 A &amp; B: 返回双方都包含的部分, 可用于判断某个或某些位是否存在<br>使用 A &amp; ~B : A中有没有B都去掉B,不影响其他位<br>使用 A | B: A中有没有B都加上B, 不影响其他位
                                                                                        </div>
页: [1]
查看完整版本: E_ALL &amp; ~E_NOTICE 与 E_ALL ^ E_NOTICE