0

我有一些我想移植到java的C代码。我没有做过太多的 C 编码,但我能够一直跟进到这个函数。如果有人可以帮助我了解发生了什么,将不胜感激。

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

I'll be happy to post Java code that does the same as the C code, but only if you promise not to use it.

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

Note that there's no point in looping - an int in Java is always 4 bytes. Also note the triple-right angle bracket at the beginning the expression to perform an unsigned right-shift.

Now for the reasons not to use it:

1 - The function already exists - see Integer.reverseBytes(int)

2 - You're going to have a hard time using that example code, since Java doesn't let you cast an array of bytes as anything else. Java is officially big-endian (most significant byte first), so if you're reading bytes from a file then you can use java.io.DataInputStream to extract ints, longs, etc.

于 2009-12-13T00:48:45.830 回答
5

它正在反转整数的字节顺序(字节序)。

程序员使用的地方似乎也有一个错误3,假设它会是sizeof(int) - 1

于 2009-12-13T00:10:26.953 回答
2

There is one very serious problem with this function: it is solving a standard problem that has available solutions. In short, it is re-inventing the wheel.

Well, I'm making an assumption here. I'm assuming that the reason for reversing the integer is to convert from little-endian to big-endian or vice versa. The usual reason for this is that you are on a little-endian computer (any Intel or AMD x86 chip) and you need to send ore receive data from a network in "network order", i.e. big-endian.

If I am correct in my assumption, in C you can call one of:

ntohl()
hlton()

More info on these functions here:

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

If you are already on a big-endian computer, and you want to reverse the integer for some other reason, then these calls won't help you (because "network order" is big-endian, so if you are already on a big-endian computer, hlton() will not change anything).

I did a Google search for "Java ntohl" and found these links:

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

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

So, I think you may not need to port this at all; you can perhaps just grab a solution from one of these two links.

于 2009-12-13T00:45:54.513 回答
1

该功能正在反转字节顺序,在大端和小端数据之间转换时需要。大多数网络协议要求 32 位整数以 Big Endian 顺序存储,但 Intel 处理器以 Little Endian 顺序存储数字,因此在向网络读取或写入数据时需要交换字节顺序。(这适用于低级别的东西,不适用于 HTTP 等数字作为文本传输的协议。)

我相信该函数实际上会像常规 Java 一样编译,除了sizeof(int),您可以用 4 替换它,因为 JVM 定义int为 32 位宽(在 C 中,没有保证)。

它看起来像是position一个二进制数据块,而不是一个字符串。position 的类型是char *,表示指向字符(1 字节)的指针。

The expression *position would dereference that pointer, getting the 1 byte it is pointing to. However, the author of the code wanted a full int's worth of bytes from the data block. (4 bytes if compiled for a 32-bit architecture; 8 bytes for 64-bit machine.)

So, to get the full int, the pointer is cast from a byte pointer to an int pointer: (int *)position. Then, because we want the value at that address, we stick an asterisk in front to dereference it: *(int *)position.

于 2009-12-13T00:28:50.277 回答
1

[too large for a comment] If you put the output <<= 8 at the beginning of the loop you can avoid one 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;
}

This function reverses the bytes in an int. An input of 0x12345678, in an implementation where CHAR_BIT is 8 and sizeof (int) is 4 (the most usual nowadays), returns 0x78563412.

于 2009-12-13T00:36:17.283 回答
0

I suggest the following code to byte swap ints:

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
}

Where U16, U32 and U64 as integer types of that size.

The asm is for gcc.

于 2009-12-13T00:47:51.383 回答