代码之家  ›  专栏  ›  技术社区  ›  Alex

C++按位操作反转

  •  -1
  • Alex  · 技术社区  · 8 年前

    我做了以下手术:

    uint8_t input = 10;
    uint8_t output = ((0x190 - (input * 8)) & 0xFF);
    
    // newInput should be 10 again, but is 255
    uint8_t newInput = (((output * 8) + 0x190) | 0xFF);
    

    如何更正操作设置 newInput 所以它将在10年后返回?

    3 回复  |  直到 8 年前
        1
  •  2
  •   The Vee    8 年前

    你想逆转你的转变 output 从…起 input | 不是 & * 8 * 8 .此外,如果您想反转 y = 0x190 - x 不是 + 而是另一个 x = 0x190 - y (在纸上试试!)最后,如果所有操作都正常,则需要颠倒操作顺序以撤消它们(先入后出)。

    输入 (从数学上讲,它不是内射的。)考虑:

    uint8_t input = 10;
    uint8_t output = ((0x190 - (input * 8)) & 0xFF); /* 0x40 */
    
    uint8_t input2 = 42;
    uint8_t output2 = ((0x190 - (input2 * 8)) & 0xFF); /* also 0x40! */
    

    如果您有一个函数可以撤消操作,那么 输出 属于 0x40 输入

    可以在无符号8位计算中撤消的操作示例如下:

    • 常数的加减: y = x + a x = y - a ,
    • 从常数中减去: y = c - x x = c - y 包括简单的否定( c = 0),
    • 异或: y = x ^ p x = y ^ p 包括…在内 ~x (那是 x ^ 0xFF ),
    • 乘以中的常数 一些 情况(奇数),但相反的情况并不明显。

    复合式的逆运算 y = -((x + 0x17) ^ 0x15) 看起来像 x = ((-y) ^ 0x15) - 0x17 ,请注意撤消步骤的相反顺序。

    另一方面,这些是不可逆的:

    • 并且,
    • 或者,
    • 乘以偶数,
    • 位移位,

    有时候你可以找到 如果对你可行的话,倒过来。在这里,如果你保证 输入 介于 0 18 0x90 / 8 )你可以试试

    uint8_t input = 10;
    uint8_t output = 0x90 - (input * 8); // spot two differences
    uint8_t newInput = (0x90 - output) / 8;
    

    但是如果 输入 如果较大,例如20,则它将给出一些其他值,这些值恰好产生相同的值 输出 .

        2
  •  2
  •   izlin    8 年前

    1. 0x190 - (10 *8) = 0x190 - 0x50 = 0x140 可以这样做,但之后用&FF,因此您丢失了以后无法恢复的信息。
    2. 这个 | FF 0xFF = 255 ,而不考虑您的输出。
    3. 你的计算错了。
    4. 在一次计算中使用十进制数(10)和十六进制数(0x190)是危险的。这可能会令人困惑。

    我建议确保变量不会溢出。使用其他常数,使您保持在第八单元\u t的范围内,或使用其他类型,如int16\u t,它不会用这些小数字溢出。 请注意您的位运算符。如我所说,最后一个OR将始终使newInput=255。

    下面是一个适用于给定参数的示例:

    int16_t input = 10; // int16_t wont overflow
    int16_t output = ((0x190 - (input * 8)) ); // without &FF there is no
                                                // loss of information
    
    int16_t newInput = (0x190- output) / 8; // Reshape of the line obove
    
        3
  •  1
  •   Community Mohan Dere    8 年前

    这里有几点:

    1. 您似乎正在尝试使用 & 0xFF 要截断为8位,您应该去掉它,因为标准已经保证无符号整数会发生这种情况: https://stackoverflow.com/a/36234166/2642059
    2. 你应该这样做 (0x190 - output) / 8U 要恢复输入,即使允许的大小是错误的:

    o=400-8x

    (o-400)/-8=x

    1. 400二进制是 0b1'1001'0000 因此,由于下行是截断最高有效位,因此它可能设置,也可能不设置,因此您将始终有两个可能的答案(其中 output 为正):
    const uint8_t newInputSmall = (0x190 - (output | 0b1'0000'0000)) / 8U;
    cosnt uint8_t newInputLarge = (0x190 - output) / 8U;
    
    1. 您需要处理以下可能性: 输出 是否定的,因为 input * 8U