web-dev-qa-db-ja.com

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つの引数を取ります...($ include_hidden = false、$ return_absolute = false、$ 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 );

等...

どのフラグが呼び出されたかをテストするという観点から、これをどのように実装しますか?

69

実際には非常に簡単です。最初に、実装方法を示すためのコードを少し紹介します。このコードが何をしているのか、どのように機能するのかについて何も理解していない場合は、コメントで追加の質問をしてください。

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);

デモ


フラグは整数であるため、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...

フラグを組み合わせて関数に渡すとき、ORそれらを一緒にします。FLAG_1 | FLAG_3を渡すとどうなるか見てみましょう。

  00000001
| 00000100
= 00000101

そして、どのフラグが設定されているかを見たいときは、ビットマスクとフラグを合わせます。したがって、上記の結果を取得して、FLAG_3が設定されているかどうかを確認しましょう。

  00000101
& 00000100
= 00000100

...フラグの値、ゼロ以外の整数を取得します-ただし、FLAG_2が設定されているかどうかを確認した場合:

  00000101
& 00000010
= 00000000

...ゼロになります。つまり、値が渡されたかどうかをチェックするときに、AND演算の結果をブール値として単純に評価できるということです。

140
DaveRandom
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
}
17
Esailija

他のものは良い提案を提供しましたが、最近では、ビットマスクの代わりに連想配列を渡すのがはるかに一般的です。より読みやすく、真/偽の値以外の他の変数を渡すことができます。このようなもの:

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

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

    if ($options['includeHidden']) {
        ...
    }
    ...
}
3
Simon East