0


0

Cコードの移植。ビット単位の操作とポインター構文の助けが必要

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

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

    for ( i=0, i>= 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 )

6 Answer


7


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

/** Reverses the bytes in an integer. */
   public static int reverseInteger(int input) {
      return
         (input >>> 24) |
         (input >> 8) & 0x0000ff00 |
         (input << 8) & 0x00ff0000 |
         (input << 24);
   }

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

今、それを使用しない理由:

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

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


5


整数のバイト順(_http://en.wikipedia.org/wiki/Endianness [endianness] _)を逆にします。

また、プログラマが「sizeof(int)-1」と仮定して「3」を使用するバグがあるようです。


2


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

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

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

ntohl()
hlton()

これらの機能の詳細はこちら:

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

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

したがって、これをまったく移植する必要はないと思う。これらの2つのリンクのいずれかからソリューションを入手することができます。


1


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

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

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

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

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


1


_ [コメントには大きすぎる] _ループの先頭に「出力<< = 8」を配置すると、1つの「if」を回避できます。

#include
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」の入力、「CHAR_BIT」が8で「sizeof(int)」が4(現在最も一般的)の実装では、「0x78563412」を返します。


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用です。