当我尝试在 Java 中(从 C++ 通过 JNI)重新组合这两个字节时,我没有得到预期的结果。下面的例子:
C++:
uint8_t originalValue = 0x38;
uint8_t high = originalValue & 0x0f0; //equals to 0x30
uint8_t low = originalValue << 4; //equals to 0x80
sendByte(high);
delayNs(1);
sendByte(low);
Java:
private int[] instructionRegister = new int[2];
private void processData(byte[] data) {
if (data.length <= 0)
return;
if (data.length == 1) {
int tmp = data[0];
String hexTmp = ByteUtils.toHexString(false, (byte) tmp).toUpperCase();
switch (tmp) {
case CMD_INSTRUCTION: {
log.info("\t>> INSTRUCTION: {}", hexTmp);
processingInstruction = true;
break;
}
case CMD_DATA: {
log.info("\t>> DATA: {}", hexTmp);
break;
}
default: {
log.info("\t\t- {}", hexTmp);
if (processingInstruction) {
if (instructionCount == 0) {
instructionRegister[0] = tmp;
instructionCount++;
} else {
instructionRegister[1] = tmp;
int combined = instructionRegister[0] | ((instructionRegister[1] >> 4);
log.info("\t>> Combined: ({}, {}) = {}",
ByteUtils.toHexString(false, (byte) instructionRegister[0]),
ByteUtils.toHexString(false, (byte) instructionRegister[1]),
ByteUtils.toHexString(false, (byte) combined));
instructionRegister = new int[2];
instructionCount = 0;
processingInstruction = false;
}
}
}
}
结果:
>> Combined: (30 , 80 ) = f8
我预计这是 0x38 但得到的是 0xF8。当我在 speedcrunch 中手动进行计算时,我得到了预期的结果。
最佳答案
就像我在评论中所说的那样,问题是将包含 0x80
的带符号字节转换为 int
(使用扩大转换),因为字节是负数,并且然后符号被扩展,所以你在 int
中得到 ffffff80
。如果您随后将其向右移动 4 位并转换回 byte
,您将得到:0xf8
,如果您使用二进制或 0x30
它仍然是 0xf8
。
看起来你只是在这里做这样的转换:
int tmp = data[0];
您可以将此行更改为:
int tmp = Byte.toUnsignedInt(data[0]);
将字节视为无符号进行转换。
演示差异:
byte b = (byte) 0x80; // force overflow, making -128
int i1 = b;
int i2 = Byte.toUnsignedInt(b);
System.out.println(String.format("%x", b)); // 80
System.out.println(String.format("%x", i1)); // ffffff80
System.out.println(String.format("%x", i2)); // 80
关于java - 从 C++ 在 Java 中重新组装两个字节,没有得到预期的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51340101/