2012-08-09 46 views
60

我不确定位掩码是否正确。让我来解释:如何在php中实现位掩码?

在PHP中error_reporting函数可以调用多种方式:

// Report simple running errors 
error_reporting(E_ERROR | E_WARNING | E_PARSE); 

// Reporting E_NOTICE can be good too (to report uninitialized 
// variables or catch variable name misspellings ...) 
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); 

// Report all errors except E_NOTICE 
// This is the default value set in php.ini 
error_reporting(E_ALL^E_NOTICE); 

我从php.net页here

反正这点是长期位掩码,我实现了一个叫做ls的SIMPLE方法,它返回一个目录的内容。

这个函数有3名ARGS ...($ include_hidden =假,$ return_absolute =假,$ EXT = FALSE)

所以当我调用函数,我设置我多么希望的结果。无论是我想要的结果返回隐藏的目录,我是否要基本名称只等

所以,当我打电话我正在写

ls(true, false, true) 
ls(false, false, true) 
ls(true, true, true) 
etc... 

功能我认为它会如果我能更加可读举报我想如何返回数据?

所以像:

ls(INCLUDE_HIDDEN | HIDE_EXTS); 
ls(SHOW_ABSOLUTE_PATHS | HIDE_EXTS); 

等等

我怎么会在这标志已经被称为测试方面实现这一点?

+1

好问。 KISS – Nico 2015-10-26 17:14:26

回答

121

这是很简单的实际。首先介绍一些代码来演示如何实现它。如果你不理解的任何事情这个代码做什么或它是如何工作的,随便问其他问题的意见:

const FLAG_1 = 0b0001; // 1 
const FLAG_2 = 0b0010; // 2 
const FLAG_3 = 0b0100; // 4 
const FLAG_4 = 0b1000; // 8 
// Can you see the pattern? ;-) 

function show_flags ($flags) { 
    if ($flags & FLAG_1) { 
    echo "You passed flag 1!<br>\n"; 
    } 
    if ($flags & FLAG_2) { 
    echo "You passed flag 2!<br>\n"; 
    } 
    if ($flags & FLAG_3) { 
    echo "You passed flag 3!<br>\n"; 
    } 
    if ($flags & FLAG_4) { 
    echo "You passed flag 4!<br>\n"; 
    } 
} 

show_flags(FLAG_1 | FLAG_3); 

Demo


因为国旗是整数,上一个32位的平台,你最多可以定义32个标志。在64位平台上,它是64.也可以将标志定义为字符串,在这种情况下,可用标志的数量或多或少是无限的(当然,在系统资源的范围内)。以二进制方式工作(为简单起见,缩减为8位整数)。

FLAG_1 
Dec: 1 
Binary: 00000001 

FLAG_2 
Dec: 2 
Binary: 00000010 

FLAG_3 
Dec: 4 
Binary: 00000100 

// And so on... 

当你结合标志将它们传递给函数,你或他们在一起。让我们看看会发生什么,当我们通过FLAG_1 | FLAG_3

00000001 
| 00000100 
= 00000101 

而当你想看到哪些设置标志,你和标志位掩码。所以,让我们看看上面的结果,看看是否设置了FLAG_3

00000101 
& 00000100 
= 00000100 

...我们得到的标志的值后面,一个非零整数 - 但如果我们看看设置:

00000101 
& 00000010 
= 00000000 

...我们得到零。这意味着您可以在检查值是否通过时简单地将AND操作的结果评估为布尔值。

+5

所以基本的按位操作是:'$ flags&FLAG_1' - 检查是否设置了FLAG_1 ,'$ flags | FLAG_1' - 设置FLAG_1,'$ flags&〜FLAG_1' - 取消设置FLAG_1,'〜$ flags' - 反转标志 – 2013-11-01 16:53:33

+5

我不知道PHP并且可能永远不会学习它,但很高兴我偶然发现了这个问题 - 你的解释可以帮助任何人实现任何语言的位映射:) – 2013-12-03 04:29:43

+3

我会建议定义功率2小数为1的位移操作。'define('FLAG_1',1 << 0); define('FLAG_2',1 << 2); define('FLAG_3',1 << 3); define('FLAG_4',1 << 4);'这是通常在C – AmitP 2014-01-06 16:12:32

14
define("INCLUDE_HIDDEN", 0x1); 
define("HIDE_EXTS", 0x2); 
define("SHOW_ABSOLUTE_PATHS", 0x4); 
//And so on, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800 etc.. 

然后,您可以检查各个标志在ls功能:

if($flags & INCLUDE_HIDDEN) { //<-- note just a single &, bitwise and 
    //$flags have INCLUDE_HIDDEN 
} 
+7

你知道使用十六进制数字而不是整数的好处吗?只是好奇:) – 2014-09-16 14:21:19

+0

@ AlexMorley-Finch看起来像纯粹的偏好,使用小数或十六进制似乎根本没有改变执行时间,要么 – 2018-01-22 19:38:13

3

其他人提供了很好的建议,但现在通过关联数组而不是位掩码更为常见。它更可读,并允许您传递其他变量,而不仅仅是true/false值。这样的事情:

myFunction(['includeHidden' => true, 'fileExts' => false, 'string' => 'Xyz']); 

function myFunction($options) { 
    // Set the default options 
    $options += [ 
     'includeHidden' => false, 
     'fileExts' => true, 
     'string' => 'Abc', 
    ]; 

    if ($options['includeHidden']) { 
     ... 
    } 
    ... 
} 
+0

我也是这样做的,但同伴们抱怨他们的IDE没有“类型暗示”,没有合适的[doc comments](https://en.wikipedia.org/wiki/PHPDoc)和函数不会[在需要的参数不通过时抛出错误](http://symfony.com/doc/current/components/options_resolver.html)。理想情况下,“命名参数”将解决所有这些问题,如果它们存在于php – 2015-10-31 08:43:47

+0

Hi @TimoHuovinen - 感谢评论。添加概述选项和默认值的doc注释非常简单,如果需要可以引发异常,并将参数默认为允许提示类型的数组。这对你有用吗? – 2015-10-31 08:49:30

+0

哦,我明白了。 Symfony OptionsResolver类进一步提供更多功能。凉。 – 2015-10-31 08:53:58