将十进制字符串 IP 掩码转换为带有尾随零的无符号整数
Posted
技术标签:
【中文标题】将十进制字符串 IP 掩码转换为带有尾随零的无符号整数【英文标题】:Convert decimal string IP mask to unsigned int with trailing zeros 【发布时间】:2022-01-21 23:03:49 【问题描述】:我得到一个掩码作为我使用strtol
和strtok
检索的字符串,我想保存在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->x = -1;
之后的内存视图
我们可以看到它确实设置了所有位
curr_IP->x &= ~(1U << i);
i = 31
之后的内存视图
预计fffffffe
【问题讨论】:
请尝试创建一个合适的minimal reproducible example 向我们展示。对“输入”进行硬编码,并包含IPV4_LENGTH
之类的内容。
还可以尝试使用调试器逐条执行代码语句,同时监控变量及其值。如果您将更复杂的表达式拆分为更小更简单的表达式,并分配给临时变量,这将很有帮助。例如,curr_IP->x &= ~(1UL << i);
可以是 unsigned long temp1 = 1UL << i; unsigned long temp2 = ~temp1; unsigned long temp3 = curr_IP->x & temp2; curr_IP->x = temp3;
更容易查看和验证您的表达式和计算。
@Someprogrammerdude 希望这就够了
@RedYoel 请记住,类型的大小取决于编译器。例如,Microsoft 编译器仍然使用 32 位 long
,即使在 64 位系统上也是如此。
@RedYoel int
已签名且已签名溢出是未定义的行为!所以使用unsigned int
或包含<stdint.h>
并使用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->x
现在是 uint32_t
,正如你所建议的那样!
是的,但 mask
和 i
已签名。为什么要混合签名?我认为 IPv4 地址始终是未签名的或者..?我认为这是编译器经常警告的(混合签名)以上是关于将十进制字符串 IP 掩码转换为带有尾随零的无符号整数的主要内容,如果未能解决你的问题,请参考以下文章
在 Rust 中将二进制字符串转换为带有前导零的十六进制字符串