How to implement a bitmask in php?

Ale*_*nch 69 php bitmask

I'm not sure if bitmask is the correct term. Let me explain:

In php, the error_reporting function can be called multiple ways:

// 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);
Run Code Online (Sandbox Code Playgroud)

I got the term bitmask from the php.net page here

Anyway the point of this is, I have implemented a SIMPLE method called ls which returns the contents of a directory.

这个函数有3个args ...($ include_hidden = false,$ return_absolute = false,$ ext = false)

因此,当我调用该函数时,我设置了我想要的结果.我是否希望结果返回隐藏目录,是否只需要基本名称等.

所以,当我打电话给我正在写的功能

ls(true, false, true)
ls(false, false, true)
ls(true, true, true)
etc...
Run Code Online (Sandbox Code Playgroud)

如果我只能标记我想要的数据返回,我认为它会更具可读性?

像这样的东西:

ls( INCLUDE_HIDDEN | HIDE_EXTS );
ls( SHOW_ABSOLUTE_PATHS | HIDE_EXTS );
Run Code Online (Sandbox Code Playgroud)

等等...

我将如何在测试哪些标志被调用方面实现这一点?

Dav*_*dom 141

实际上这很简单.首先是一些代码来演示它是如何实现的.如果您对此代码的作用或工作原理一无所知,请随时在评论中提出其他问题:

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);
Run Code Online (Sandbox Code Playgroud)

演示


因为标志是整数,所以在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...
Run Code Online (Sandbox Code Playgroud)

当您组合标志以将它们传递给函数时,您将它们组合在一起.让我们来看看当我们通过时会发生什么FLAG_1 | FLAG_3

  00000001
| 00000100
= 00000101
Run Code Online (Sandbox Code Playgroud)

当你想看到设置了哪些标志时,你和带有标志的位掩码.所以,让我们看看上面的结果,看看是否FLAG_3已设置:

  00000101
& 00000100
= 00000100
Run Code Online (Sandbox Code Playgroud)

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

  00000101
& 00000010
= 00000000
Run Code Online (Sandbox Code Playgroud)

......我们得到零.这意味着在检查值是否通过时,您可以简单地将AND运算的结果作为布尔值进行求值.

  • 所以基本的按位运算是:`$ flags&FLAG_1` - 检查FLAG_1是否设置,`$ flags | FLAG_1` - 设置FLAG_1,`$ flags&~FLAG_1` - 取消设置FLAG_1,`〜$ flags` - 反转标志 (8认同)
  • 我不知道PHP并且可能永远不会学习它,但我很高兴我偶然发现了这个问题 - 你的解释可以帮助任何人实现任何语言的位映射:) (7认同)
  • @AmitP在PHP中,这种方法存在一些(次要的)问题.1)当前`const`关键字不支持表达式,即使结果是常量(即`const FLAG_1 = 1 << 0;`是一个解析错误) - 显然这不是`define()`2的问题)在C中一个常量表达式,如`const int FLAG_1 = 1 << 0;`将在编译时解析,实际编译的值将是表达式的结果,而在PHP中这是每次评估,一个微观性能击中.这两个问题都不是避免你建议的更易读的版本的好理由. (6认同)
  • 我建议将幂2的小数定义为1的位移位操作.`define('FLAG_1',1 << 0); define('FLAG_2',1 << 2); define('FLAG_3',1 << 3); define('FLAG_4',1 << 4);`这就是它通常在C中完成的方式 (5认同)

Esa*_*ija 17

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..
Run Code Online (Sandbox Code Playgroud)

然后,您可以检查ls函数中的各个标志:

if( $flags & INCLUDE_HIDDEN ) { //<-- note just a single &, bitwise and
    //$flags have INCLUDE_HIDDEN
}
Run Code Online (Sandbox Code Playgroud)

  • 你知道使用十六进制数而不是整数的优势吗?只是好奇:) (7认同)