Porting C code; need help with bitwise operation and pointer syntax

£可爱£侵袭症+ 提交于 2019-12-11 17:11:50

问题


I have some C code that I'd like to port to java. I haven't done much C coding, but I was able to follow along up until this one function. If anyone could help me understand what is going on, it would be greatly appreciated.

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

The function is used as such:

char * position = //some data

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

回答1:


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.




回答2:


It is reversing the byte order (the endianness) of an integer.

There also appears to be a bug where the programmer uses 3, assuming it will be sizeof(int) - 1.




回答3:


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.




回答4:


The function is reversing byte-order, as needed when converting between big endian and little endian data. Most network protocols required 32-bit integers be stored in Big Endian order, but Intel processors store numbers in Little Endian order, so you need to swap byte orders when reading or writing data to the network. (This applies to low level stuff, not for protocols like HTTP where numbers are transmitted as text.)

I believe the function would actually compile as regular Java, with the exception of sizeof(int), which you could replace with 4 since the JVM defines int to be 32 bits wide (in C, there are no guarantees).

It looks like position is a block of binary data, not a string. The type of position is char *, which means a pointer to a character (1 byte).

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.




回答5:


[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.




回答6:


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.



来源:https://stackoverflow.com/questions/1895131/porting-c-code-need-help-with-bitwise-operation-and-pointer-syntax

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!