【问题标题】:The opposite of bitwise AND按位与的相反
【发布时间】:2023-03-24 00:07:01
【问题描述】:

我不喜欢这么多嵌套的 if,这就是为什么我想要与该条件相反的 if (section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)。那会是什么?我试过if (section_header[i].Characteristics & ~IMAGE_SCN_MEM_WRITE) continue,但不是正确的。

for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i)
{
    if (functions[i] >= section_header[i].VirtualAddress && functions[i] < section_header[i].VirtualAddress + section_header[i].Misc.VirtualSize)
    {
        if (section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
        {
            ... next
        }
    }
}

【问题讨论】:

  • if(!(section_header[i].Characteristics &amp; IMAGE_SCN_MEM_WRITE))?
  • if ((section_header[i].Characteristics &amp; IMAGE_SCN_MEM_WRITE) == 0)?
  • 如果IMAGE_SCN_MEM_WRITE 只是一位,您可以使用if (~section_header[i].Characteristics &amp; IMAGE_SCN_MEM_WRITE),但它的可读性较差。
  • 您似乎正在寻找不存在的按位 NAND。但是~(a &amp; b) (~a | ~b) 如果你愿意的话。
  • @nop:好的,现在你知道你可以了。我还是说不要。 !(value &amp; MASK)(value &amp; MASK) == 0 中的任何一个都更具惯用性和可读性,并且所有三个都可能编译为完全相同的代码:godbolt.org/z/cna43vfGa

标签: c++ bitwise-operators bitwise-and


【解决方案1】:

翻转条件是减少“箭头代码”(大量缩进代码)的常见做法:

for (WORD i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) {
    if(!(section_header[i].VirtualAddress < functions[i] && functions[i] < section_header[i].VirtualAddress + section_header[i].Misc.VirtualSize)) {
        continue;
    }
    if((section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE) == 0) {
        continue;
    }
    // From this point
    // It's now guaranteed that selected function is in range and
    // the selected section_header contains the IMAGE_SCN_MEM_WRITE bit
}

【讨论】:

    【解决方案2】:

    如果您确定您的掩码只会设置一个位,那么您可以通过以下操作测试该位是否在value 中被清除(即未设置)

    if (~value & MASK)
        // bit is clear
    

    但是,我不建议这样做。虽然逻辑上正确,但它比其他建议的选项 if (!(value &amp; MASK))if ((value &amp; MASK) == 0) 要少得多。阅读您的代码的人更容易产生误解,可能导致他们通过“修复”它来创建新的错误。

    此外,如果 MASK 应该设置多个位,则表达式 ~value &amp; MASK 表达式将在 value 中清除 任何 位时为真,因此它是不再是value &amp; MASK 的逻辑否定。例如,如果MASK == 0x3value == 0x2,则value &amp; MASK 为真,~value &amp; MASK 也为真。相比之下,!(value &amp; MASK) 为真,如果所有这些位都被清除。

    【讨论】:

      【解决方案3】:

      首先您需要确定“特征”项目的类型。是 uint32_t 吗?这很重要,因为如果您尝试融合不兼容的类型,AND 操作可能会混淆。

      我会这样做:

      ...
      auto typed_flag = (uint32_t)IMAGE_SCN_MEM_WRITE;
      if (((section_header[i].Characteristics bitand typed_flag) == typed_flag) 
      {
          continue;
      }
      ...
      

      注意:'bitand' 比 & 符号更 C++(尽管两者的作用完全相同)。

      【讨论】:

      • bitand is more C++-ish。不,不是。这是一个alternative,用于没有适当语言支持的字符集。它适用于 C 和 C++。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 2014-02-15
      • 2011-11-13
      • 1970-01-01
      相关资源
      最近更新 更多