将十进制字符串 IP 掩码转换为带有尾随零的无符号整数

Posted

技术标签:

【中文标题】将十进制字符串 IP 掩码转换为带有尾随零的无符号整数【英文标题】:Convert decimal string IP mask to unsigned int with trailing zeros 【发布时间】:2022-01-21 23:03:49 【问题描述】:

我得到一个掩码作为我使用strtolstrtok 检索的字符串,我想保存在unsigned int x 中,用零结尾,& 它的IP 也表示为@987654330 @ 为了只保留 MSB(最后我要将该 IP 与另一个 IP 进行比较)。

我的想法是设置x的所有位,然后关闭掩码大小之后的所有位:

#define IPV4_LENGTH 32

//subent is "123.34.45.66/31"

curr_IP->address = malloc(sizeof (struct in_addr));
token = strtok(subnet, "/");
inet_aton(token, curr_IP->address);
long mask  = strtol(strtok(NULL, "/"), NULL, 10);
curr_IP->x = -1;
for(long i=mask; i<=IPV4_LENGTH; i++)
    curr_IP->x &= ~(1U << i);

示例:如果掩码 = 31,我想以 11111111111111111111111111111110 结尾,以 unsigned int 表示 -> FFFFFFFE 以十六进制表示

PS掩码不能为0

更新: curr_IP-&gt;x = -1;之后的内存视图

我们可以看到它确实设置了所有位

curr_IP-&gt;x &amp;= ~(1U &lt;&lt; i);i = 31 之后的内存视图

预计fffffffe

【问题讨论】:

请尝试创建一个合适的minimal reproducible example 向我们展示。对“输入”进行硬编码,并包含 IPV4_LENGTH 之类的内容。 还可以尝试使用调试器逐条执行代码语句,同时监控变量及其值。如果您将更复杂的表达式拆分为更小更简单的表达式,并分配给临时变量,这将很有帮助。例如,curr_IP-&gt;x &amp;= ~(1UL &lt;&lt; i); 可以是 unsigned long temp1 = 1UL &lt;&lt; i; unsigned long temp2 = ~temp1; unsigned long temp3 = curr_IP-&gt;x &amp; temp2; curr_IP-&gt;x = temp3; 更容易查看和验证您的表达式和计算。 @Someprogrammerdude 希望这就够了 @RedYoel 请记住,类型的大小取决于编译器。例如,Microsoft 编译器仍然使用 32 位 long,即使在 64 位系统上也是如此。 @RedYoel int 已签名且已签名溢出是未定义的行为!所以使用unsigned int 或包含&lt;stdint.h&gt; 并使用uint32_t 来获得32 位编译器 【参考方案1】:

我选择了不同的方法;关闭掩码,然后将相关位设置为 1。

long mask  = strtol(strtok(NULL, "/"), NULL, 10);
curr_IP->x = 0; //mask to 0
for(long i=IPV4_LENGTH - mask; i<IPV4_LENGTH; i++)
    curr_IP->x |= (1U << i); //Sets the ith bit of the mask

编辑:正如 Morten Jensen 所指出的,最好不要混合有符号和无符号整数,因此更正后的代码如下所示:

unsigned long mask  = strtol(strtok(NULL, "/"), NULL, 10);
curr_IP->x = 0; //mask to 0
for(unsigned long i=IPV4_LENGTH - mask; i<IPV4_LENGTH; i++)
    curr_IP->x |= (1U << i); //Sets the ith bit of the mask

另外,我自己也很难调试代码,因为我使用了内存视图,却没有意识到我应该从从右到左阅读它。

在图片#2中,我以为我得到了fffffff7,而实际上它是7fffffff

【讨论】:

你保留了我看到的有符号整数:P? @MortenJensen 实际上 curr_IP-&gt;x 现在是 uint32_t,正如你所建议的那样! 是的,但 maski 已签名。为什么要混合签名?我认为 IPv4 地址始终是未签名的或者..?我认为这是编译器经常警告的(混合签名)

以上是关于将十进制字符串 IP 掩码转换为带有尾随零的无符号整数的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有尾随x的数字字符串转换为无符号数字列表

在 Rust 中将二进制字符串转换为带有前导零的十六进制字符串

将十进制转换为小数点后两个零的字符串,和逗号? C# [重复]

JS:将带有尾随零的数字替换为科学记数法

将带有掩码和符号的 SVG 转换为纯 SVG 文件?

使用python将数据帧从十六进制转换为二进制