将逆序的整数转换为逆序的IP地址。

huangapple go评论80阅读模式
英文:

Converting integer in reverse order to gererate IP in reverse order

问题

我想要按相反的顺序生成IP地址。

生成IP地址的功能如下所示:

val := 1<<(32-prefixLen) // 假设prefixLen为24
IP4(val) = IP4(256) = 0.0.1.0

我想要按相反的顺序获得IP地址,即0.1.0.0,所以将val转换为相反顺序的字节,并将其发送到IP4()函数。

我尝试的功能导致整数溢出:

temp1:=byte(val*0xff<<24)    
temp2:=byte(val*0xff00<<16)   
temp3:=byte(val*0xff0000<<8)
temp4:=byte(val*0xff000000)  
valReverse := uint32(temp4)|uint32(temp3)|uint32(temp2)|uint32(temp1)
IP4(valReverse)=0.1.0.0 //期望的结果
英文:

I wanted to generate IP in reverse order.

Functionality which generate IP address is as follow:

val := 1&lt;&lt;(32-prefixLen) // let take prefixLen as 24
IP4(val) = IP4(256) = 0.0.1.0

I wanted the IP in reverse order i.e., 0.1.0.0, so convert the val in reverse order bytes and send it to IP4() function.

Functionality which I have tried resulted in integer overflow:

temp1:=byte(val*0xff&lt;&lt;24)    
temp2:=byte(val*0xff00&lt;&lt;16)   
temp3:=byte(val*0xff0000&lt;&lt;8)
temp4:=byte(val*0xff000000)  
valReverse := uint32(temp4)|uint32(temp3)|uint32(temp2)|uint32(temp1)
IP4(valReverse)=0.1.0.0 //expected

答案1

得分: 2

反转字节

首先,你需要使用uint32类型而不是byte类型,因为byte值只有8位(超过8的位位置不存在)。

其次,你需要使用按位与运算符&,而不是乘法运算符*

第三,移位的值是不正确的。看看这个可行的示例:

prefixLen := uint32(24)

var val uint32
val = 1 << (32 - prefixLen)
fmt.Printf("%08x\n", val)

temp1 := uint32(val & 0xff << 24)
temp2 := uint32(val & 0xff00 << 8)
temp3 := uint32(val & 0xff0000 >> 8)
temp4 := uint32(val & 0xff000000 >> 24)
valReverse := uint32(temp4) | uint32(temp3) | uint32(temp2) | uint32(temp1)

fmt.Printf("%08x\n", valReverse)

输出结果(在Go Playground上尝试):

00000100
00010000

但是个人建议直接使用net.IP类型,该类型使用字节切片表示IP地址,可以使用切片反转算法简单地反转字节。

代码如下:

ip := net.IPv4(0, 0, 1, 0).To4()
fmt.Println(ip)

// 反转:
for i, j := 0, len(ip)-1; i < j; i, j = i+1, j-1 {
    ip[i], ip[j] = ip[j], ip[i]
}
fmt.Println(ip)

输出结果(在Go Playground上尝试):

0.0.1.0
0.1.0.0

注意:如果你有一个uint32类型的IP值,仍然可以使用net.IP类型,像这样创建net.IP值:

ip := net.IPv4(byte(val>>24), byte(val>>16), byte(val>>8), byte(val)).To4()

反转位

如果你想要反转位,你需要逐位进行操作。一种可能的解决方案如下:

prefixLen := uint32(24)

var val uint32
val = 1 << (32 - prefixLen)
fmt.Printf("%08x\n", val)

var valReverse uint32
for i := 0; i < 32; i, val = i+1, val>>1 {
    valReverse = valReverse<<1 | val&0x01
}
fmt.Printf("%08x\n", valReverse)

输出结果(在Go Playground上尝试):

00000100
00800000

另一种可能更复杂的反转位的方法:

var valReverse uint32
for mask1, mask2 := uint32(0x01), uint32(0x80000000); mask2 != 0; mask1, mask2 = mask1<<1, mask2>>1 {
    if val&mask1 != 0 {
        valReverse |= mask2
    }
}

输出结果相同,可以在Go Playground上尝试这个变体。

英文:

Reversing bytes

First, you have to use uint32 type instead of byte as a byte value only has 8 bits (bit positions above 8 don't exist).

Next, you have to use bitwise AND which is &amp; and not the multiplication *.

Third, the shift values are incorrect. See this working example:

prefixLen := uint32(24)

var val uint32
val = 1 &lt;&lt; (32 - prefixLen)
fmt.Printf(&quot;%08x\n&quot;, val)

temp1 := uint32(val &amp; 0xff &lt;&lt; 24)
temp2 := uint32(val &amp; 0xff00 &lt;&lt; 8)
temp3 := uint32(val &amp; 0xff0000 &gt;&gt; 8)
temp4 := uint32(val &amp; 0xff000000 &gt;&gt; 24)
valReverse := uint32(temp4) | uint32(temp3) | uint32(temp2) | uint32(temp1)

fmt.Printf(&quot;%08x\n&quot;, valReverse)

Output (try it on the Go Playground):

00000100
00010000

But personally I would just use the net.IP type which models an IP address with a byte slice, and using that you can simply reverse the bytes with a slice-reversing algorithm.

This is how it would look like:

ip := net.IPv4(0, 0, 1, 0).To4()
fmt.Println(ip)

// Reverse:
for i, j := 0, len(ip)-1; i &lt; j; i, j = i+1, j-1 {
	ip[i], ip[j] = ip[j], ip[i]
}
fmt.Println(ip)

Output (try it on the Go Playground):

0.0.1.0
0.1.0.0

Note: if you have the IP as a value of uint32, you can still use the net.IP type, creating the net.IP value like this:

ip := net.IPv4(byte(val&gt;&gt;24), byte(val&gt;&gt;16), byte(val&gt;&gt;8), byte(val)).To4()

Reversing bits

If you want to reverse bits, you have to do that bit-by-bit. One possible solution is this:

prefixLen := uint32(24)

var val uint32
val = 1 &lt;&lt; (32 - prefixLen)
fmt.Printf(&quot;%08x\n&quot;, val)

var valReverse uint32
for i := 0; i &lt; 32; i, val = i+1, val&gt;&gt;1 {
	valReverse = valReverse&lt;&lt;1 | val&amp;0x01
}
fmt.Printf(&quot;%08x\n&quot;, valReverse)

Output (try it on the Go Playground):

00000100
00800000

An alternative, maybe more complex way to reverse the bits:

var valReverse uint32
for mask1, mask2 := uint32(0x01), uint32(0x80000000); mask2 != 0; mask1, mask2 = mask1&lt;&lt;1, mask2&gt;&gt;1 {
	if val&amp;mask1 != 0 {
		valReverse |= mask2
	}
}

Output is the same, try this variant on the Go Playground.

huangapple
  • 本文由 发表于 2016年11月10日 15:23:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/40522005.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定