【问题标题】:php bitwise flag detection operationphp按位标志检测操作
【发布时间】:2012-11-07 08:00:21
【问题描述】:

// 嗨,我想用按位运算排除一个标志,但我不知道如何: // 这里是标志(它们来自文件系统迭代器)

define('CURRENT_AS_FILEINFO', 0);
define('CURRENT_AS_SELF', 16);
define('CURRENT_AS_PATHNAME', 32);
define('CURRENT_MODE_MASK', 240);
define('KEY_AS_PATHNAME', 0);
define('KEY_AS_FILENAME', 256);
define('FOLLOW_SYMLINKS', 512);
define('KEY_MODE_MASK', 3840);
define('NEW_CURRENT_AND_KEY', 256);
define('SKIP_DOTS', 4096);
define('UNIX_PATHS', 8192);

用户可以设置任何标志组合。 我需要检测是否设置了 CURRENT_AS_SELF 或 CURRENT_AS_PATHNAME, 所以这是我到目前为止的功能:

function containsPathnameOrSelfFlag($flags) {
    if ($flags & (CURRENT_AS_PATHNAME | CURRENT_AS_SELF)) {
        return true;
    }
    return false;
}

这是一个测试套件:

var_dump(containsPathnameOrSelfFlag(CURRENT_MODE_MASK | CURRENT_AS_PATHNAME)); // true, ok
var_dump(containsPathnameOrSelfFlag(CURRENT_AS_FILEINFO)); // false, ok
var_dump(containsPathnameOrSelfFlag(CURRENT_MODE_MASK | CURRENT_AS_FILEINFO)); // true, but false was expected, because neither CURRENT_AS_SELF nor CURRENT_AS_SELF were set, so my function is wrong

是否可以使用位运算符使函数通过第三种情况 (它应该返回 false ) ?

我在这里看到的问题是 CURRENT_MODE_MASK 的位与 CURRENT_AS_SELF 重叠 和 CURRENT_AS_PATHNAME 的位:

0000000000010000 : CURRENT_AS_SELF 
0000000000100000 : CURRENT_AS_PATHNAME 
0000000011110000 : CURRENT_MODE_MASK 
0000000100000000 : KEY_AS_FILENAME
0000001000000000 : FOLLOW_SYMLINKS
0000111100000000 : KEY_MODE_MASK
0000000100000000 : NEW_CURRENT_AND_KEY
0001000000000000 : SKIP_DOTS
0010000000000000 : UNIX_PATHS

所以每次用户将 CURRENT_MODE_MASK 添加到标志时,我的函数 会认为 CURRENT_AS_SELF 和 CURRENT_AS_PATHNAME 也已设置,但事实并非如此。 我不知道如何解决这个问题。

【问题讨论】:

  • CURRENT_MODE_MASK 确实设置了 CURRENT_AS_SELF 和 CURRENT_AS_PATHNAME 标志...将其更改为 0000000011000000
  • 感谢您的回答,但标志来自 FilesystemIterator 类,我无法更改它们,但也许我误解了 CURRENT_MODE_MASK 的工作原理
  • 您必须以不同的方式检查标志。见我的answer
  • 我认为还值得注意的是 KEY_MODE_MASK 在技术上没有设置为正确的值,因为 KEY_MODE_MASK & FOLLOW_SYMLINKS 返回一个真实的结果,即使 FOLLOW_SYMLINKS 与任何键都不相关标志。因此拥有$any_key_flag_set = $fsiObj->getFlags() & $fsiObj::KEY_MODE_MASK; 将返回误报。 KEY_MODE_MASK 应该是 3328(从它的掩码中删除 512),或者 FOLLOW_SYMLINKS 应该是 16384 以将其从 3840 掩码中取出。

标签: php bit-manipulation


【解决方案1】:

掩码旨在与当前值进行与测试,而不是与新值进行生成。如果您想测试是否存在或仅使用单个标志,则仅使用该标志。

【讨论】:

  • 感谢您的回答。 “面具的目的是与当前的测试值相乘,而不是与新的生成值相乘。”你的意思是如果用户像这样构造 FilesystemIterator 他是错的吗? $o = new FilesystemIterator(DIR, FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::CURRENT_MODE_MASK);如果是这样,那么我的问题不应该被发布,我的问题已经解决了(或者至少不是一个真正的用例)
  • 正确。应该使用掩码将感兴趣的特定标志与getFlags() 隔离开来,而不是为新的迭代器设置标志。
  • 感谢您的精确,很难找到有关该标志的有用信息。 php' 文档只会说:Masks FilesystemIterator::current(),这对某些人来说可能是可以理解的(唉,对我来说不是),而我创建的唯一“文档”在这里chat.stackoverflow.com/transcript/11/2011/3/20/8-21,这也让我感到困惑。现在我想我明白了。谢谢。
【解决方案2】:

如果您不希望 CURRENT_MODE_MASKCURRENT_AS_SELFCURRENT_AS_PATHNAME 重叠,只需确保它们不共享设置为 1 的公共位。 例如,您可以将 CURRENT_MODE_MASK 设置为 64 或 192 以适应当前值。

【讨论】:

  • 感谢您的回答,但我无法更改 CURRENT_MODE_MASK 的值,它来自 FilesystemIterator 类:php.net/manual/en/class.filesystemiterator.php。我不确定 CURRENT_MODE_MASK 是如何工作的,也许它不应该与 CURRENT_AS_SELF 和 CURRENT_AS_PATHNAME 一起使用,但是当用户使用 CURRENT_MODE_MASK 和( CURRENT_AS_SELF 或 CURRENT_AS_PATHNAME )标志设置标志时不会引发错误。
猜你喜欢
  • 2022-04-09
  • 2018-08-27
  • 1970-01-01
  • 2011-02-12
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-08
相关资源
最近更新 更多