VB6 IP4 - 根据位数计算网络掩码(长)

发布于 2024-08-22 20:04:37 字数 980 浏览 9 评论 0原文

给定输入 0 到 32,表示 IP4 网络掩码中一位的数量(对应于 /19 中的 CIDR 块大小),

  1. 将其转换为四字节长网络掩码的优雅方法
  2. 是什么?将其转换为四字节长的网络掩码的方法

原型:

Function NetMaskFromBitCount(BitCount As Long) As Long
   'Logic here '
End Function

请注意,VB6 不执行无符号操作,因此情况变得很复杂,因此常规数学技巧通常不起作用。如果 (Number And &H80000000) 不为零,则 Number \ 2 将与 SHR 操作不同。

我想出了一些方法,但我认为它们并不优雅,而且可能没有那么快。

我的一个想法是策略性地使用 CopyMemory API,它非常快。过去,我通过将 Long 写入一个字节(0 到 3)并根据需要处理每个部分来解决一些有符号/无符号的 Long 问题。

由于我也在使用 inet_ntoa() 和 inet_addr() Windows API 函数,并且它们以相反的字节顺序返回 IP 序列号,因此以相反的顺序返回字节的解决方案很棒(我已经有一个函数可以翻转如果需要字节顺序,但避免它也很好)。

示例:

Input = 2
Output = -1073741824 (&HC0000000)
Alternate Output = 12 (&HC0, reverse byte order)

Input = 19
Output = -8192  (&HFFFFE000)
Alternate Output = 14745599 (&H00E0FFFF, reverse byte order)

可行的解决方案很好,但我正在寻找优雅或快速的解决方案。

Given input of 0 to 32, representing the number of one-bits in an IP4 network mask (corresponding to a CIDR block size as in /19), what's

  1. An elegant way to turn that into a four-byte long net mask
  2. A fast way way to turn that into a four-byte long net mask

Prototype:

Function NetMaskFromBitCount(BitCount As Long) As Long
   'Logic here '
End Function

Notice this is complicated by the fact that VB6 doesn't do unsigned, so regular math tricks often don't work. If (Number And &H80000000) is nonzero, then Number \ 2 will NOT be the same as a SHR operation.

I've come up with a few ways, but I don't think they're elegant, and they're probably not that fast.

One idea I had is to strategically use the CopyMemory API, which is VERY fast. I've solved some signed/unsigned Long problems in the past by just blatting the Long into a Byte(0 To 3) and working with each portion as needed.

Since I'm also working with the inet_ntoa() and inet_addr() Windows API functions and they return the IP serial number in reverse byte order, a solution that returns the bytes in reverse order is great (I already have a function to flip the byte order if needed, but avoiding it would be nice, too).

Examples:

Input = 2
Output = -1073741824 (&HC0000000)
Alternate Output = 12 (&HC0, reverse byte order)

Input = 19
Output = -8192  (&HFFFFE000)
Alternate Output = 14745599 (&H00E0FFFF, reverse byte order)

Working solutions are good, but ELEGANT or FAST is what I'm looking for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉殇 2024-08-29 20:04:37
Function NetMaskFromBitCount(ByVal lBitCount As Long) As Long
    If lBitCount > 0 Then
        NetMaskFromBitCount = -1 * 2 ^ (32 - lBitCount)
    End If
End Function

必须使这个参数ByVal

测试如下:

Debug.Assert NetMaskFromBitCount(19) = &HFFFFE000
Debug.Assert NetMaskFromBitCount(2) = &HC0000000
Debug.Assert NetMaskFromBitCount(32) = &HFFFFFFFF
Debug.Assert NetMaskFromBitCount(0) = 0
Function NetMaskFromBitCount(ByVal lBitCount As Long) As Long
    If lBitCount > 0 Then
        NetMaskFromBitCount = -1 * 2 ^ (32 - lBitCount)
    End If
End Function

Had to make this param ByVal!

And the test goes here:

Debug.Assert NetMaskFromBitCount(19) = &HFFFFE000
Debug.Assert NetMaskFromBitCount(2) = &HC0000000
Debug.Assert NetMaskFromBitCount(32) = &HFFFFFFFF
Debug.Assert NetMaskFromBitCount(0) = 0
我一向站在原地 2024-08-29 20:04:37

你只有 32 个可能的输入,所以我猜测最快的解决方案将是 查找表 引用数组中的所有 32 个输出。它不会为优雅赢得分数。警告:空中代码

Function DoIt(ByVal Input As Long) As Long  
  Static lArray() As Long  
  Static bInitialised As Boolean   
  If Not bInitialised Then   
    ReDim Preserve lArray(0 To 31)   
    lArray(0) = 0   
    lArray(1) = &H80000000    
    lArray(2) = &HC0000000    
    ' etc... '  
    bInitialised = True 
  End If
  DoIt = lArray(Input)  ' for bonus marks raises an error on illegal input ' 
End Function  

如果你想要什么更一般地说,VBSpeed 对于快速 VB6 左移有着长期的公开竞争。

  • 这是当前的获胜者 ShiftLeft04,它使用了一些可怕的,抱歉,我的意思是在 VB6 中获得内联汇编器的绝妙技巧。你会笑,你会哭,你会惊恐地尖叫……
  • 当前的亚军ShiftLeft06 是大约 200 行的全原生 VB6。需要 1.3 倍的时间,但仍然很快。

You only have 32 possible inputs, so my guess is the fastest solution will be a lookup table referencing all 32 outputs from an array. It won't win points for elegance. Warning: air code

Function DoIt(ByVal Input As Long) As Long  
  Static lArray() As Long  
  Static bInitialised As Boolean   
  If Not bInitialised Then   
    ReDim Preserve lArray(0 To 31)   
    lArray(0) = 0   
    lArray(1) = &H80000000    
    lArray(2) = &HC0000000    
    ' etc... '  
    bInitialised = True 
  End If
  DoIt = lArray(Input)  ' for bonus marks raises an error on illegal input ' 
End Function  

If you want something more general, VBSpeed has a long-standing open competition for fast VB6 left-shifts.

  • Here's the current winner ShiftLeft04 which uses some horrendous, sorry I mean brilliant, tricks to get inline assembler in VB6. You'll laugh, you'll cry, you'll scream in terror...
  • The current runner-up ShiftLeft06 is about 200 lines of all-native VB6. Takes 1.3 times longer, but still quick.
随波逐流 2024-08-29 20:04:37

我没有 VB6,但这是我在 .Net 中的做法

    Const allBroadcast As Integer = Integer.MaxValue ' = 2,147,483,647
    Dim mask As Integer
    'three examples
    mask = allBroadcast << (32 - 24) '/24
    mask = allBroadcast << (32 - 16) '/16
    mask = allBroadcast << (32 - 8) '/8

I don't have VB6, but here is how I would do it in .Net

    Const allBroadcast As Integer = Integer.MaxValue ' = 2,147,483,647
    Dim mask As Integer
    'three examples
    mask = allBroadcast << (32 - 24) '/24
    mask = allBroadcast << (32 - 16) '/16
    mask = allBroadcast << (32 - 8) '/8
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文