我有一个由另一个程序员编写的Java函数,它使用按位操作。我需要一个能够撤消进程的函数(如果可能的话)。也许你们中的一些人比我对这些运营商更精明。以下是需要撤消的内容:
public void someFunc(int[] msg, int[] newMsg) {
int i = SOME_LENGTH_CONSTANT;
for (int j = 0; j < newMsg.length; j++) {
// msg[i] Shift left by 8 bits bitwise or with next msg[i+1]
// then bitwise not (~) and bitwise and with $FFF
newMsg[j] = (~(((msg[i] & 0x0f) << 8) | (msg[i + 1]))) & 0xfff;
i += 2;
}
}
答案 0 :(得分:1)
我的版本,不料:
public void undoFunc(int[] newMsg, int[] original) {
int i = SOME_LENGTH_CONSTANT; // starting point
for (int j = 0; j < newMsg.length; j++) { // Iterate over newMsg
original[i] = ~((newMsg[j]&0xff00)>>8)&0x000f; // &0x000f to get rid of "mistakes" when NOT-ing
original[i+1] = (~(newMsg[j]&0x00ff)) & 0xff;
// i = initial value + 2 * j
i+=2;
}
}
您的代码有什么作用?
输入是整数数组。每两个值用于在&#39;输出中创建一个值。 (newMsg
)数组。
msg[i+1]
放在最右边四位的零中。&0x0FFF
撤消它。 迭代示例:
msg[i] == 1010'1011
msg[i+1] == 0010'0100
1) 1010'1011 -> 0000'1011
2) 0000'1011 -> 0000'1011'0000'0000
3) 0000'1011'0000'0000 -> 0000'1011'0010'0100
4) 0000'1011'0010'0100 -> 1111'0100'1101'1011
5) 1111'0100'1101'1011 -> 0000'0100'1101'1011
newMsg[j] == 0000'0100'1101'1011 == 0x04DB (I think, from memory)
我的代码的作用:
获得(以前的)msg[i+1]
的值很容易,它与最右边的8位相反/ NOT
。因为否定它会将所有前导零变为1,所以AND
将0xff
与msg[i]
进行对比。
获得(曾经是)&0x000f
的价值更加困难。首先向左滚动最左边的8位。然后我否定了价值。但是四个未使用/丢失的位现在是1,我希望OP希望这些为零,所以我0000'0100'1101'1011
它。
注意:我使用带有前导零的六边形使其更清晰。这些都没有必要
注意:为了便于阅读,我将二进制数分成四位。因此0b
实际上是{0000010011011011
)msg[i+1]
。
msg[i]
的值已恢复,但&
的最左边四位丢失。
Fwew。
在您的代码中,您使用&
。 a
所做的是,所有人都同意这些比特&#39; (当来自字节1
的位和来自字节b的同等有效位都是1)进入0
s而其余位进入&
s。这意味着,正如@Mike Harris所说,不同意的所有内容都会消失。
示例1010 & 0110 =
1 & 0 => 0
0 & 1 => 0
1 & 1 => 1
0 & 0 => 0
= 0010
(和操作):
a
如您所见,只保留字节1
的第二和第三最高有效位(或零包含第一和第二最低有效位)(第4位/#0是&#39;运气&# 39;),因为它们是字节b
中的1
。
您可以反转代码中b
字节fff
的所有位(其中一个为1111 1111 1111
,或二进制为1111 1111 1111 == 000000000...00111111111111
,但请记住所有位删除比第一个更重要,因为<java jar="${eclipse.equinox.launcher.plugin}" fork="true" failonerror="true">
<arg value="-application"/>
<arg value="org.eclipse.ant.core.antRunner"/>
<arg value="-buildfile"/>
<arg value="${eclipse.pde.build.plugin}/scripts/productBuild/productBuild.xml"/>
<arg value="-Dbuilder=${build.directory.projectroot}"/>
</java>
)。但这不会逆转它,只能根据逆转它的目的而起作用。
答案 1 :(得分:0)
我只想尝试这样做,这是我尝试的结果。
一开始我将表达式拆分为单个操作:
int t1 = msg[i] & 0x0f;
除了最后4位,我们失去了所有。
int t2 = t1 << 8;
通过移位t1
清除低8位。
int t3 = t2 | msg[i + 1];
我们应该了解m[i + 1]
是否大于255(特别是m[i + 1] & 0xf00 > 0
),我们无法恢复m[i]
的低4位,因为它们会被不可逆转地覆盖。
int t4 = ~t3;
只是否定。
newMsg[j] = t4 & 0xfff;
低12位。
只是按相反的顺序执行了这些步骤:
public static void someFuncRev(int[] msg, int[] newMsg) {
for (int i = 0; i < msg.length; ++i) {
newMsg[2 * i] = (~msg[i] >> 8) & 0xf; // take 11-8 bits
newMsg[2 * i + 1] = ~msg[i] & 0xff; // take 7-0 bits
}
}
我假设SOME_LENGTH_CONSTANT == 0
。调整常数很容易。
因此,当msg
内的值<= 15时,上述函数将恢复初始序列。
在值> 15且<= 255的情况下,对于msg[i]
,我们只能恢复4位,msg[i + 1]
完全恢复。
如果值> 255,我们无法恢复msg[i]
,因为它是由msg[i + 1]
的位进行校正(在第3点看上面);可以恢复8位msg[i + 1]
。
我希望这会对你有所帮助。