C ++按位运算反向

时间:2016-12-03 22:04:14

标签: c++ bitwise-operators bit-shift

我做了以下操作:

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?

1 个答案:

答案 0 :(得分:2)

您想要反转从output获得input的转换,但遗憾的是逻辑存在缺陷。 |不是&的倒数,* 8绝对不与另一个* 8相反。另外,如果您想要撤销y = 0x190 - x的操作,它不是+而是另一个x = 0x190 - y(在纸上试试!)最后,如果您拥有所有操作可以,操作的顺序需要反转才能撤消它们(先进先出)。

实际上,您的转换不能被反转,因为它会丢失定义input的部分信息。 (从数学上讲,它不是单射的。)考虑一下:

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! */

如果你有一个可以撤消操作的函数,那么output 0x40,10或42的返回值是多少?这没有解决方案。如果您想要原始input,则需要在某处保留该变量的副本。

无符号8位计算中可以撤消的操作示例是

  • 加法和减法常量:y = x + ax = y - a
  • 从常量减去:y = c - xx = c - y,包括明显否定(c = 0),
  • XOR:y = x ^ px = y ^ p,包括~x(' s x ^ 0xFF),
  • 乘以某些个案例中的常数(乘以奇数),但反过来并不明显。

对像y = -((x + 0x17) ^ 0x15)这样的化合物的逆操作看起来像x = ((-y) ^ 0x15) - 0x17,请注意步骤撤消的相反顺序。

另一方面,这些不可逆转:

  • AND,
  • 乘以偶数,
  • 位移,

有时你可以找到 逆,如果这对你有用的话。在此,如果您保证input介于018之间(即0x90 / 8),则可以尝试

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

但如果input较大,例如20,则它会提供一些其他值来生成相同的output