我有一些我想要移植到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 )
答案 0 :(得分: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是官方的big-endian(最重要的字节优先),所以如果你从文件中读取字节,那么你可以使用java.io.DataInputStream
来提取整数,长整数等。
答案 1 :(得分:5)
它正在反转整数的字节顺序( endianness )。
程序员使用3
似乎还有一个错误,假设它是sizeof(int) - 1
。
答案 2 :(得分:2)
此功能存在一个非常严重的问题:它正在解决具有可用解决方案的标准问题。简而言之,它正在重新发明轮子。
好吧,我在这里做一个假设。我假设反转整数的原因是从little-endian转换为big-endian或反之亦然。通常的原因是您使用的是小端计算机(任何Intel或AMD x86芯片),您需要以“网络顺序”(即big-endian)从网络发送矿石接收数据。
如果我的假设是正确的,在C中你可以打电话给其中一个:
ntohl()
hlton()
这里有关于这些功能的更多信息:
http://www.codeguru.com/forum/showthread.php?t=298741
如果您已经在大端计算机上,并且由于某些其他原因想要反转整数,那么这些调用对您没有帮助(因为“网络订单” 大 - endian,所以如果你已经在大端计算机上,hlton()
将不会改变任何东西。)
我在谷歌搜索“Java ntohl”并找到了这些链接:
http://www.velocityreviews.com/forums/t139571-ntohl-ntohs-etc.html
http://www.coderanch.com/t/366549/Java-General/java/Java-equivilent-c-functions-htonl
所以,我认为你可能根本不需要移植它;你也许可以从这两个链接之一中获取解决方案。
答案 3 :(得分:1)
在big endian和little endian数据之间进行转换时,该函数正在按字节顺序反转。大多数网络协议要求32位整数以Big Endian顺序存储,但Intel处理器以Little Endian顺序存储数字,因此在向网络读取或写入数据时需要交换字节顺序。 (这适用于低级别的东西,而不适用于HTTP等协议,其中数字作为文本传输。)
我相信该函数实际上会编译为常规Java,但sizeof(int)
除外,你可以用4代替,因为JVM将int
定义为32位宽(在C中,有没有保证)。
看起来position
是二进制数据块,而不是字符串。位置类型为char *
,表示指向字符的指针(1个字节)。
表达式*position
将取消引用该指针,获取它指向的1个字节。但是,代码的作者想要从数据块中获得完整int的字节数。 (如果针对32位架构进行编译,则为4个字节;对于64位计算机,则为8个字节。)
因此,要获得完整的int,指针将从字节指针转换为int指针:(int *)position
。然后,因为我们想要该地址的值,我们在前面贴上一个星号来取消引用它:*(int *)position
。
答案 4 :(得分:1)
[评论太大] 如果您将output <<= 8
放在循环的开头,则可以避免一个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且CHAR_BIT
为4(现在最常见)的实施中,sizeof (int)
,的输入会返回0x78563412
。< / p>
答案 5 :(得分:0)
我建议使用以下代码进行字节交换:
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。