簡體   English   中英

帶有負數的Java Bitshift錯誤?

[英]Java Bitshift error with negatives?

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());
}

Java使用漂亮的常規整數運算。 關於C和C ++的兩個主要特點是

  1. Java除了char (16位寬)外沒有其他無符號整數類型,並且
  2. Java具有單獨的算術( >> )和邏輯( >>> )右移運算符。 前者通過用左操作數的最高有效位的副本填充結果的所需最高有效位來保留符號,而后者則用零填充結果的最高有效位。

Java的優勢在於,所有原始類型在所有平台上均具有眾所周知的一致大小和符號,並且它的兩個右移運算符對所有有效操作數具有明確定義的語義。 相反,在C中,對負值執行右移的結果是實現定義的, 所有標准數據類型都具有實現定義的大小,而某些類型( char )具有實現定義的符號。

但是,既然您已經發布了一些代碼,看來所有這些實際上都不是您的問題。 我不知所措,您為什么會認為否定數字會進行任何形式的轉換,或者實際上,為什么您認為您要進行的操作根本需要進行轉換。

特別要注意的是,Java使用二進制補碼表示形式(這也是迄今為止C編譯器的最常見選擇),因此,數字取反的含義不只是符號位。 相反,如果您只想設置int的符號位,則可以將其拼寫為

value.length() | 0x80000000

如果您要通過電線接收byte s,則將對它們進行簽名,這意味着最高有效位將是符號位。 如果要從byte提取符號位,則有兩種明智的方法:通過與0比較或使用>>>運算符而不是>>運算符來測試負性。

下面的代碼顯示了我如何在C中反序列化這樣一個帶signed char數組。我無法想象為什么在Java中這種方法不起作用,假設data是一個byte s數組……盡管我確定這將是非常可怕的。

long offset = 0;
long nameLength  = data[offset] >= 0 ? data[offset++] : (-(long)data[offset++] << 24)
                                                      + ( (long)data[offset++] << 16)
                                                      + ( (long)data[offset++] <<  8)
                                                      +         data[offset++];
long valueLength = data[offset] >= 0 ? data[offset++] : (-(long)data[offset++] << 24)
                                                      + ( (long)data[offset++] << 16)
                                                      + ( (long)data[offset++] <<  8)
                                                      +         data[offset++];

for (long x = 0; x < nameLength; x++) {
    /* XXX: Copy data[offset++] into name */
}

for (long x = 0; x < valueLength; x++) {
    /* XXX: Copy data[offset++] into value */
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM