【问题标题】:What does (x ^ 0x1) != 0 mean?(x ^ 0x1) != 0 是什么意思?
【发布时间】:2014-01-07 21:36:22
【问题描述】:

我遇到了以下代码sn-p

if( 0 != ( x ^ 0x1 ) )
     encode( x, m );

x ^ 0x1 是什么意思?这是一些标准技术吗?

【问题讨论】:

  • Code obfuscation 很标准。
  • 这可以用与“正常”方程相同的方法求解:0 != (x ^ 1) → 两边异或 1 → (0 ^ 1) != (x ^ 1 ^ 1) → 简化 → 1 != x
  • 我看不出if (1 != x)有多难写。
  • Various cmets,首先由 @Spook,明确指出 xtype 没有给出 - 因此我们不知道这是这个 C++ 标记问题中的整数。当然,如果这是 C 或 x 是整数,答案很简单,但这不是给定的,并且存在重载 operator ^ 的可能性。
  • 我不明白这是怎么得到这么多支持的......

标签: c++ c bit-manipulation bitmask


【解决方案1】:
  • ^ 是按位运算 XOR
  • 0x1 是十六进制的1
  • x ^ 0x1 将反转 x 的最后一位(如果您不清楚,请参阅上面链接中的 XOR 真值表)。

因此,如果 x 大于 1 或 x 的最后一位为 0,则条件 (0 != ( x ^ 0x1 )) 将为真。这仅留下 x==1 作为条件为假的值.所以相当于

if (x != 1)

P。 S. 地狱般的方式来实现这样一个简单的条件,我可能会补充。不要那样做。如果您必须编写复杂的代码,请发表评论。我求求你了。

【讨论】:

  • 不是x==0; 4 ^ 0x1 是真的,但4==0 显然是假的。
  • "条件好像等于if (x == 0)",不等于x != 1吗?
  • 等价假设x是一个整数类型。如果它是floatdouble,那么我相信该表达式会为1.0 <= x < 2.0 生成真值。如果x 是用户定义的类型,如果x 是Yugo、袋鼠、著名作曲家的生日或任何与当前以美元计价的茶叶价格至少有三位的数字,则表达式可能会返回true中国。
  • @supercat operator^ 没有 float/double
  • @supercat:当调用从浮点到整数的转换时,转换是隐式的(不需要强制转换语法)。但是按位运算符不会触发转换,它们对于浮点类型只会失败。
【解决方案2】:

^ 运算符是按位异或。而0x1 是数字1,写成十六进制常量。

因此,x ^ 0x1 的计算结果与 x 相同,但最低有效位被翻转。

代码只是将 x 与 1 进行比较,以一种非常复杂和晦涩的方式。

【讨论】:

    【解决方案3】:

    XOR 操作 (x ^ 0x1) 将位 0 ​​取反。因此该表达式实际上意味着:如果 x 的位 0 为 0,或 x 的任何其他位为 1,则表达式为真。

    相反,如果 x == 1,则表达式为假。

    所以测试是一样的:

    if (x != 1)
    

    因此(可以说)被不必要地混淆了。

    【讨论】:

    • 嘿,你不知道上下文。如果 x 是某种位标志,IMO 实际上比使用 != 运算符更清楚地写它现在的样子。
    • @Spook:它不只是测试单个位标志 - 它正在测试 x 的整个宽度。如果您只想测试一个位,那么还有更清晰的习语,例如使用按位与。
    • 不必要的混淆?难道你不知道混淆代码是我们的工作。如果我们编写任何人都可以理解的简单代码,为什么,我们在世界上的宗教神圣地位会去哪里?我们会突然像其他人一样成为普通工人。混淆本质上是必要的。
    • 其实 Spook 是对的。测试 (x != 1) 不等价。代码可以是 C++(在 C++ 中,^ 可以是一个可以做任何事情的运算符)。所以你不知道上下文,@Spook 是对的。
    • @TheThom уєт уσυ ωяιтє ιи ¢ℓєαя тєχт
    【解决方案4】:

    它会检查 x 实际上不是 0x1... xoring x0x1 只有在 x0x1 时才会导致 0 ...这是一个老把戏主要用在汇编语言中

    【讨论】:

    • 这比!= 1快吗?
    • 如果我没记错的话,在古代进行手动装配优化(x86)时,xor 方法包含的机器代码更少,并且执行速度比对0 的相应分配要快...但是这个问题包含一个xor 和一个比较,所以我可能认为!= 可能更快。不过我不太确定,是否需要查看一些编译器生成的程序集。
    • @BitFiddlingCodeMonkey:不。如果 XOR 比某些本机级别的相等测试更快,您的编译器将发出 XOR 来测试相等性。因此,XOR 永远不会比优化编译器的相等测试更快。编写快速代码的规则 101 是“不要试图帮助编译器。你最终只会编写出在实践中速度较慢的不可读代码”。
    • @fritzone IIRC,XOR 技巧更多地与保存寄存器有关,保存寄存器加载 b/c 在某些情况下,文字可以直接在 OP 中编码,并且与状态标志有一些细微差别(但我的大部分程序集都是在 68k 和 DSP 上)。
    • @MPD:通常与清除寄存器有关(至少在 386+ 上)。 xor eax, eax 在两个字节中将 eax 设置为零,但 mov eax, 0 需要三个或六个字节(取决于编码),并且解码时间比xor 形式。
    【解决方案5】:

    ^c 中是按位的xor operator。在您的情况下,x 与 1 进行异或运算。例如,x 的值为 10,然后 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d 则条件为真。

    【讨论】:

    • 您的答案中的错字。 10 != 1010
    • @BitFiddlingCodeMonkey:您的评论中有错字:10 (decimal) == 1010 (binary)
    • @PaulR 如果你不在那里放b 或其他东西,怎么会有人知道什么是十进制和什么是二进制?
    • 0b1010 不会是 Pythonic 的做事方式吗?
    【解决方案6】:

    它是异或(XOR)运算符。要了解它是如何工作的,您可以运行这个简单的代码

        std::cout << "0x0 ^ 0x0 = " << ( 0x0 ^ 0x0 ) << std::endl;
        std::cout << "0x0 ^ 0x1 = " << ( 0x0 ^ 0x1 ) << std::endl;
        std::cout << "0x1 ^ 0x0 = " << ( 0x1 ^ 0x0 ) << std::endl;
        std::cout << "0x1 ^ 0x1 = " << ( 0x1 ^ 0x1 ) << std::endl;
    

    输出将是

    0x0 ^ 0x0 = 0
    0x0 ^ 0x1 = 1
    0x1 ^ 0x0 = 1
    0x1 ^ 0x1 = 0
    

    所以这个表达式

    0 != ( x ^ 0x1 )
    

    只有当 x != 0x1 时才等于 true。

    它不会改变 x 本身。它只检查 x 是等于 0 还是 1。这个 rxpression 可以更改为

    if ( x != 0x1 )
    

    【讨论】:

      【解决方案7】:

      xor(异或)运算符最常用于反转一位或多位。 该操作是询问是否恰好其中一位为1,这导致以下真值表(A和B是输入,Y是输出):

      A    B    Y
      0    0    0
      0    1    1
      1    0    1
      1    1    0
      

      现在这段代码的目的似乎是检查最后一位是否为 1,其他位是否为 0,这等于 if ( x != 1 )。 这种晦涩难懂的方法的原因可能是使用了先前的位操作技术,并且可能在程序的其他地方使用了。

      【讨论】:

        【解决方案8】:

        这可能看起来过于简单的解释,但如果有人想慢慢看,下面是:

        ^ 是 c、c++ 和 c# 中的 bitwise XOR 运算符。

        按位异或需要两个长度相等的位模式并执行 对每一对对应位进行逻辑异或运算。

        异或是一种逻辑运算,只要两者都输出真 输入不同(一个为真,另一个为假)。

        a xor btruth table

        a           b        a xor b
        ----------------------------
        1           1           0
        1           0           1
        0           1           1
        0           0           0
        

        让我们来说明二进制级别的0 == ( x ^ 0x1 ) 表达式:

                     what? xxxxxxxx (8 bits)
                       xor 00000001 (hex 0x1 or 0x01, decimal 1)    
                     gives 00000000
        ---------------------------
        the only answer is 00000001
        

        所以:

           0 == ( x ^ 0x1 )    =>    x == 1
           0 != ( x ^ 0x1 )    =>    x != 1
        

        【讨论】:

          【解决方案9】:

          XOR 在 C# 标志枚举中很有用。要从枚举值中删除单个标志,必须使用 xor 运算符(参考 here

          例子:

          [Flags]
          enum FlagTest { None 0x0, Test1 0x1, Test2 0x2, Test3 0x4}
          
          FlagTest test = FlagTest.Test2 | FlagTest.Test3;
          Console.WriteLine(test); //Out: FlagTest.Test2 | FlagTest.Test3
          test = test ^ FlagTest.Test2;
          Console.WriteLine(test); //Out: FlagTest.Test3
          

          【讨论】:

          • 但问题是关于 C++,而不是 C#
          • @theDmi:还有关于位操作和位掩码。 C# 中的标志枚举肯定是关于位掩码的。
          • 另外它在 C++ 中也很有用。请参阅:Stack 1Stack 2
          • 除了对按位异或运算符的一些讨论之外,这个答案似乎与原始问题没有任何关系?
          【解决方案10】:

          按位测试似乎是故意混淆,但如果底层数据是来自 IBM 大型机系统的公司数据,则可能只是编写代码以反映原始文档。 IBM 数据格式可以追溯到 1960 年代,并经常将标志编码为单词中的单个位以节省存储空间。随着格式的修改,在现有记录的末尾添加了标志字节以保持向后兼容性。例如,SMF 记录的文档可能会显示汇编语言代码,以测试单个记录中三个不同单词中的三个单独位,以确定数据是输入文件。 我对 TCP/IP 内部的了解较少,但您也可以在那里找到位标志。

          【讨论】:

            【解决方案11】:

            我猜x 中还有其他位或位域值,这是为了测试仅设置了低位。在上下文中,我猜这是默认值,因此可以跳过此编码和一些相关的m(编码可能更昂贵),因为它们都必须是默认值,在构造函数中初始化或类似的。

            解码器必须能够以某种方式推断这些值缺失。如果它们位于某个结构的末尾,则可以通过始终存在的 length 值进行通信。

            【讨论】:

              【解决方案12】:

              运算符 ^ 是按位异或(参见 &, | )。位对的结果是,

              0 ^ 0 == 0
              0 ^ 1 == 1
              1 ^ 0 == 1
              1 ^ 1 == 0
              

              所以表达式,

              ( x ^ 0x1 )
              

              反转/翻转 x 的第 0 位(其他位保持不变)。

              考虑 x 是否可以有 0x0 和 0x1 以外的值? x 为单个位域时,只能有 0x0 和 0x1 的值,但当 x 为 int(char/short/long/etc)时,bit0 以外的位会影响表达式的结果。

              给定的表达式允许 bit0 旁边的位影响结果,

              if ( 0 != ( x ^ 0x1 ) )
              

              与这个(更简单的)表达式具有等效的真实性,

              if ( x ^ 0x1 )
              

              请注意,此表达式将仅检查 bit0,

              if( 0x1 & ( x ^ 0x1 ) )
              

              所以呈现的表达式实际上结合了两个表达式检查,

              if( ( x & ~0x1 )  //look at all bits besides bit0
              ||  ( x ^ 0x1 ) ) //combine with the xor expression for bit0
              

              作者是不是打算只检查bit0,并打算使用这个表达式,

              if( 0x1 & ( x ^ 0x1 ) )
              

              或者作者打算将bit1-bitN的值和bit0的xor混合在一起?

              【讨论】:

                【解决方案13】:

                ^ 是bitwise XOR 运算符

                如果 x = 1

                          00000001   (x)       (decimal 1)
                          00000001   (0x1)     (decimal 1)
                XOR       00000000   (0x0)     (decimal 0)
                

                这里 0 == ( x ^ 0x1 )

                如果 x = 0

                          00000000   (x)       (decimal 0)
                          00000001   (0x1)     (decimal 1)
                XOR       00000001   (0x1)     (decimal 0)
                

                这里 0 != ( x ^ 0x1 )

                异或b的真值表:

                a           b        a xor b
                ----------------------------
                1           1           0
                1           0           1
                0           1           1
                0           0           0
                

                代码只是意味着

                【讨论】:

                • 真的有必要再发一个重复的答案吗?
                • 你可以说另一个答案,但不能重复。对不起,如果你介意
                【解决方案14】:

                我正在添加一个新答案,因为没有人真正解释如何直观地获得答案。

                + 的倒数是-
                ^ 的倒数是^

                你如何解决0 != x - 1x?你+ 1两边:0 + 1 != x - 1 + 11 != x
                你如何为x 解决0 != x ^ 1?你^ 1到两边:0 ^ 1 != x ^ 1 ^ 11 != x

                【讨论】:

                  【解决方案15】:

                  有很多好的答案,但我喜欢用更简单的方式来思考。

                  if ( 0 != ( x ^ 0x1 ) );
                  

                  首先。仅当参数为零时,if 语句才为假。这意味着比较不等于零是没有意义的。

                  if ( a != 0 );
                  // Same as
                  if ( a );
                  

                  所以剩下的就是:

                  if ( x ^ 0x1 );
                  

                  与一的异或。 XOR 所做的本质上是检测位不同的位。因此,如果所有位都相同,它将返回 0。由于 0 为假,它唯一会返回假的情况是所有位都相同。因此,如果参数相同则为 false,如果它们不同则为 true...就像 not equal to 运算符。

                  if ( x != 0x1 );
                  

                  如果事实上,两者的唯一区别是!=会返回0或1,而^会返回任意数字,但结果的真实性总是相同的.一种简单的思考方式是。

                  (b != c) === !!(b ^ c) // for all b and c
                  

                  最后的“简化”是将0x1 转换为十进制,即 1。因此您的语句相当于:

                  if ( x != 1 )
                  

                  【讨论】:

                    【解决方案16】:

                    到目前为止,我看到的答案错过了处理XORs 的简单规则。无需详细说明^0x 的含义(以及if!= 等),表达式0 != (x^1) 可以使用(a^a)==0 的事实进行如下修改:

                    0 != (x^1) <=> [xor left and right side by 1]
                    (0^1) != (x^1^1) <=>
                    1 != x
                    

                    【讨论】:

                      【解决方案17】:

                      可能在这里使用的标准技术是为了清晰起见重复出现在周围上下文中的习语,而不是通过用算术上更简单的习语替换它来混淆它但在上下文中没有意义。

                      周围的代码可能会频繁引用(x ^ 1),或者测试可能会询问“如果位 0 反过来,这个位掩码会为空吗?”。

                      鉴于条件导致某些内容为encode()ed,可能是在上下文中,位 0 的默认状态已被其他因素反转,并且我们只需要在任何位偏离它们的情况下编码额外信息默认(通常全零)。

                      如果你断章取意地问这个表达是做什么的,你就会忽略潜在的意图。您不妨看看编译器的程序集输出,发现它只是与 1 进行直接相等比较。

                      【讨论】:

                        猜你喜欢
                        • 2014-11-06
                        • 2018-06-05
                        • 2022-12-01
                        • 2020-09-24
                        • 2021-09-18
                        • 1970-01-01
                        • 2015-03-20
                        • 2020-01-07
                        • 2015-03-24
                        相关资源
                        最近更新 更多