英文:
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<<(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<<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 //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 &
and not the multiplication *
.
Third, the shift values are incorrect. See this working example:
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)
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 < 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>>24), byte(val>>16), byte(val>>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 << (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)
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<<1, mask2>>1 {
if val&mask1 != 0 {
valReverse |= mask2
}
}
Output is the same, try this variant on the Go Playground.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论