java - 从 C++ 在 Java 中重新组装两个字节,没有得到预期的结果

标签 java c++ type-conversion java-native-interface byte

当我尝试在 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 中手动进行计算时,我得到了预期的结果。

enter image description here

最佳答案

就像我在评论中所说的那样,问题是将包含 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/

相关文章:

java - 将平面图转换为层次图

c++ - 复制初始化和直接初始化有区别吗?

Java float 到 long Typecast

java - 将 linkedHashMap 值与 Java 中的字符串进行比较

java - Spring Batch RowMapper - 获取列数和类型

java - 我是一名 Java 编码新手,正在寻求有关如何将 .class 或 .java 源文件导入可执行 jar 文件的帮助

c++ - 将 C 程序更改为 C++ 程序 - 编译错误

c++ - 多项式类 : Polynomial Multiplication

java - 带数组的通用类

java.security.Principal - 在 HttpServletRequest 和 Spring Security 中创建