Java Bitshift错误与否定?

时间:2015-03-30 21:39:50

标签: java c++ c bit-manipulation bit

http://www.fastcgi.com/devkit/doc/fcgi-spec.html 在第3.4节中:

 typedef struct {
        unsigned char nameLengthB0;  /* nameLengthB0  >> 7 == 0 */
        unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
        unsigned char nameData[nameLength];
        unsigned char valueData[valueLength];
    } FCGI_NameValuePair11;

    typedef struct {
        unsigned char nameLengthB0;  /* nameLengthB0  >> 7 == 0 */
        unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
        unsigned char valueLengthB2;
        unsigned char valueLengthB1;
        unsigned char valueLengthB0;
        unsigned char nameData[nameLength];
        unsigned char valueData[valueLength
                ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
    } FCGI_NameValuePair14;

    typedef struct {
        unsigned char nameLengthB3;  /* nameLengthB3  >> 7 == 1 */
        unsigned char nameLengthB2;
        unsigned char nameLengthB1;
        unsigned char nameLengthB0;
        unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
        unsigned char nameData[nameLength
                ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
        unsigned char valueData[valueLength];
    } FCGI_NameValuePair41;

    typedef struct {
        unsigned char nameLengthB3;  /* nameLengthB3  >> 7 == 1 */
        unsigned char nameLengthB2;
        unsigned char nameLengthB1;
        unsigned char nameLengthB0;
        unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
        unsigned char valueLengthB2;
        unsigned char valueLengthB1;
        unsigned char valueLengthB0;
        unsigned char nameData[nameLength
                ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
        unsigned char valueData[valueLength
                ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
    } FCGI_NameValuePair44;

我在Java中实现这一点,并且为了执行valueLengthB3 >> 7 == 1等部分,我只是将其设置为否定。这不起作用。负面如何在Java中工作,以及如何在Java中执行此操作?

我目前的代码:

public void param(String name, String value) throws IOException {
    if (fp) {
        throw new IOException("Params are already finished!");
    }
    if (name.length() < 128) {
        dpout.write(name.length());
    }else {
        dpout.writeInt(-name.length());
    }
    if (value.length() < 128) {
        dpout.write(value.length());
    }else {
        dpout.writeInt(-value.length());
    }
    dpout.write(name.getBytes());
    dpout.write(value.getBytes());
}

2 个答案:

答案 0 :(得分:1)

Java使用相当常规的整数运算。与C和C ++相关的两个主要特点是

  1. Java没有char以外的无符号整数类型(16位宽),
  2. Java有单独的算术(>>)和逻辑(>>>)右移运算符。前者通过用左操作数的最高有效位的副本填充结果所需的最高有效位来保留符号,而后者用零填充结果的最高有效位。
  3. Java的优点是所有原始类型在所有平台上都具有众所周知的一致大小和签名,并且它的两个右移运算符对所有有效操作数都有明确定义的语义。相反,在C中,对负值执行右移的结果是实现定义的,标准数据类型的 all 具有实现定义的大小,以及某些类型(char )具有实现定义的签名。

    现在您已经发布了一些代码,但似乎这些都不是您的问题。我无法理解为什么你认为否定一个数字会进行任何改变,或者实际上,为什么你认为根本需要改变你想要做的事情。

    特别注意Java使用了两个补码整数表示(因为到目前为止最常见的C编译器选择),所以否定一个数字不仅仅修改了符号位。如果您只想设置int的符号位,那么您可以拼写

    value.length() | 0x80000000
    

答案 1 :(得分:0)

如果您通过线路接收byte,它们将被签名,这意味着最重要的位将是符号位。如果要从byte中提取符号位,可以想到两种明智的方法:通过与0进行比较或使用>>>运算符来测试否定性,而不是{{ 1}} operator。

以下代码显示了我如何在C中反序列化这样的>>数组。我无法想象为什么这在Java中不起作用,假设signed char是一个数组data ...虽然我确定它很可怕。

byte