2016-12-03 92 views
-1

我得到了以下操作:C++位运算反向

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?

+0

'如果值== 184值= 25 ;'? –

+2

'| (0&0x07)'什么都不做!试了一下,得到了200的25,那么'my_value'的类型是什么? –

+0

my_value是typeof uint8_t – Alex

回答

2

你想反转从input得到你output的转换,但不幸的是逻辑是有缺陷的。 |不是&* 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! */ 

如果你有这将撤消操作的功能,那会是什么预期返回为0x40,10或42的output?这没有解决办法。如果你想要原始的input,你需要在某处保留该变量的副本。

,可以在无符号8位计算来撤消操作的例子是

  • 加法和一个常数的减法:y = x + ax = y - a
  • 减法从恒定:y = c - xx = c - y,包括普通否定(c = 0),
  • XOR:y = x^px = y^p,包括~x(这是x^0xFF),
  • 乘以一个常数一些的情况下(单数),但倒数并不明显。

逆操作,以像y = -((x + 0x17)^0x15)化合物会是什么样x = ((-y)^0x15) - 0x17,注意,其中的步骤是撤消相反的顺序。

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

  • AND,
  • OR,
  • 乘以偶数,
  • 比特移位,

有时候你可以找到如果这对你来说可行的话。在这里,如果你保证input018(即0x90/8)之间,你可以尝试

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

但如果input较大,例如20,这反而给碰巧产生一些其它的值同样的output

+0

另外,即使假设您有一系列内射操作,您通常也需要按相反的顺序应用相反操作,以返回到原始值 – Caleth

+0

,例如(((输出|(魔术&0xFF00))+ 0x190)/ 8),对于魔术的某些价值 – Caleth

+0

@Caleth我在第一段的某个点添加了这样的句子,但也许你显示了以前的编辑。 –

2

有几个问题,为什么你的代码将无法正常工作,让我解释一下其中的一些:

  1. 你有一个无符号的8位整数,所以你可以为0x00到0xFF之间使用的值。 0x190 - (10 *8) = 0x190 - 0x50 = 0x140可以完成,但是之后您会用&FF删除前导1,这样会丢失以后无法恢复的信息。
  2. | FF是一个按位“或”,它将计算的每一位都变为1,所以无论输出如何,您都将获得0xFF = 255
  3. 您的计算错误。
  4. 在一次计算中使用十进制数(10)和十六进制数(0x190)是很危险的。它可能会令人困惑。

我建议确保你不会溢出你的变量。使用其他常量,所以你会留在unit8_t的范围内,或者使用另一个类型,如int16_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 
1

几点这里:

  1. 你似乎是试图用& 0xFF截断到8位,你应该摆脱,因为标准已经保证这将发生无符号整数:https://stackoverflow.com/a/36234166/2642059
  2. 你应该做(0x190 - output)/8U恢复输入,所以即使尺寸允许你的数学是错误的:

O = 400 - 8倍速
-O - 400 = -8x
(邻 - 400)/ -8 = X

  • 400以二进制为0b1'1001'0000如此以来,垂头丧气被截断它可将最显著位,不得进行设置,这样你将永远有2个可能的答案(其中output为正):
  • const uint8_t newInputSmall = (0x190 - (output | 0b1'0000'0000))/8U; 
    cosnt uint8_t newInputLarge = (0x190 - output)/8U; 
    
  • 您需要处理的可能性,即output是负的,因为input * 8U大于400