0

Java に移植したい C コードがいくつかあります。私は C コーディングをあまり行っていませんが、この 1 つの関数までフォローすることができました。何が起こっているのかを理解するのを手伝ってくれる人がいれば、大歓迎です。

int reverse_integer(int input) {
    int output = 0, i;

    for ( i=0, i<sizeof(int); i++ ) {
         output = ( input & 0x000000FF ) | output; 
         input >>= 8;
         if ( i < 3 ) {
             output <<= 8;
         }
    }

    return output;
}

関数は次のように使用されます。

char * position = //some data

/*the included comment on this next line states its the size of a string*/
int i = reverse_integer( *(int*)position ) 
4

6 に答える 6

7

C コードと同じことを行う Java コードを喜んで投稿しますが、それは使用しないと約束していただける場合に限ります。

/** 整数のバイトを反転します。*/
   public static int reverseInteger(int 入力) {
      戻る
         (入力 >>> 24) |
         (入力 >> 8) & 0x0000ff00 |
         (入力 << 8) & 0x00ff0000 |
         (入力 << 24);
   }

ループしても意味がないことに注意してくださいint。Java の an は常に 4 バイトです。また、符号なし右シフトを実行する式の先頭にある三重右山括弧にも注意してください。

使用しない理由については、次のとおりです。

1 - 関数は既に存在します - を参照してくださいInteger.reverseBytes(int)

2 - Java ではバイト配列を他のものとしてキャストできないため、このサンプル コードを使用するのは難しいでしょう。Java は正式にはビッグ エンディアン (最上位バイトが最初) であるため、ファイルからバイトを読み取る場合は、java.io.DataInputStreamint や long などを抽出するために使用できます。

于 2009-12-13T00:48:45.830 に答える
5

整数のバイト順 (エンディアン) を逆にしています。

また、プログラマーが を使用する3と仮定すると、バグが存在するようsizeof(int) - 1です。

于 2009-12-13T00:10:26.953 に答える
2

この関数には、非常に深刻な問題が 1 つあります。それは、利用可能な解がある標準的な問題を解いていることです。要するに、車輪の再発明です。

さて、私はここで仮定を立てています。整数を逆にする理由は、リトルエンディアンからビッグエンディアンに、またはその逆に変換するためだと思います。これの通常の理由は、リトルエンディアンのコンピューター (Intel または AMD x86 チップ) を使用しており、ネットワークからデータを「ネットワーク順序」、つまりビッグエンディアンで送信または受信する必要があるためです。

私の仮定が正しければ、C では次のいずれかを呼び出すことができます。

ntohl()
hlton()

これらの機能の詳細については、こちらをご覧ください:

http://www.codeguru.com/forum/showthread.php?t=298741

すでにビッグエンディアンのコンピューターを使用していて、他の理由で整数を逆にしたい場合、これらの呼び出しは役に立ちません (「ネットワーク順序」ビッグエンディアンであるため、既にビッグエンディアンにいる場合-エンディアンのコンピューターでは、hlton()何も変更されません)。

「Java ntohl」を Google で検索したところ、次のリンクが見つかりました。

http://www.velocityreviews.com/forums/t139571-ntohl-ntohs-etc.html

http://www.coderanch.com/t/366549/Java-General/java/Java-equivilent-c-functions-htonl

したがって、これを移植する必要はまったくないかもしれません。おそらく、これら 2 つのリンクのいずれかからソリューションを取得できます。

于 2009-12-13T00:45:54.513 に答える
1

この関数は、ビッグエンディアンとリトルエンディアンのデータを変換するときに、必要に応じてバイト順序を逆にします。ほとんどのネットワークプロトコルでは、32ビット整数をビッグエンディアンの順序で格納する必要がありますが、Intelプロセッサは数値をリトルエンディアンの順序で格納するため、ネットワークでデータを読み書きするときにバイト順序を入れ替える必要があります。(これは、数値がテキストとして送信されるHTTPのようなプロトコルではなく、低レベルのものに適用されます。)

関数は実際には通常のJavaとしてコンパイルされるsizeof(int)と思いますが、JVMでは32ビット幅と定義されているため4に置き換えることができますint(Cでは保証はありません)。

position文字列ではなく、バイナリデータのブロックのように見えます。位置のタイプはchar *、文字(1バイト)へのポインターを意味するです。

*positionはそのポインターを逆参照し、それが指している1バイトを取得します。ただし、コードの作成者は、データブロックから完全なintに相当するバイトを必要としていました。(32ビットアーキテクチャ用にコンパイルされた場合は4バイト、64ビットマシン用にコンパイルされた場合は8バイト。)

したがって、完全なintを取得するには、ポインターをバイトポインターからintポインターにキャストします(int *)position。次に、そのアドレスの値が必要なため、先頭にアスタリスクを付けて逆参照します*(int *)position

于 2009-12-13T00:28:50.277 に答える
1

[コメントするには大きすぎます]output <<= 8ループの先頭にを置くと、 1つを避けることができますif

#include <limits.h>
int reverse_integer(int input) {
    int output = 0, i;

    for (i = 0; i < sizeof input; i++) {
         output <<= CHAR_BIT;
         output = (input & ((1 << CHAR_BIT) - 1)) | output; 
         input >>= CHAR_BIT;
    }
    return output;
}

この関数は、intのバイトを反転します。の入力は0x12345678が8で4(現在最も一般的)である実装でCHAR_BITsizeof (int)は、を返します0x78563412

于 2009-12-13T00:36:17.283 に答える
0

int をバイトスワップするには、次のコードをお勧めします。

U16
Swap16
(
    U16 x
)
{
    return (0xFF00 & x) >> 8 | (0x00FF & x) << 8;
}


U32
Swap32
(
    U32 x
)
{
#if defined(__i386__)
    __asm__("bswap   %0" : "+r" (x));
    return x;
#else
    return (0xFF000000 & x) >> 24 |
           (0x00FF0000 & x) >> 8 |
           (0x0000FF00 & x) << 8 |
           (0x000000FF & x) << 24;
#endif
}


U64
Swap64
(
    U64 x
)
{
#if defined(__i386__)
    __asm__("bswap   %%eax\n\t"
            "bswap   %%edx\n\t"
            "xchgl   %%eax, %%edx" : "+A" (x));
    return x;
#elif defined(__x86_64__)
    __asm__("bswap   %0" : "+r" (x));
    return x;
#else
    return (0xFF00000000000000LL &
            x) >> 56 | (0x00FF000000000000LL & x) >> 40
           | (0x0000FF0000000000LL &
              x) >> 24 | (0x000000FF00000000LL & x) >> 8
           | (0x00000000FF000000LL &
              x) << 8 | (0x0000000000FF0000LL & x) << 24
           | (0x000000000000FF00LL &
              x) << 40 | (0x00000000000000FFLL & x) << 56;
#endif
}

U16、U32、および U64 は、そのサイズの整数型です。

asm は gcc 用です。

于 2009-12-13T00:47:51.383 に答える