我之前发布了如何实现一个将整数转换为IP地址字符串的函数。那么我们如何反过来呢,也就是说,给定一个字符串(154.111.23.23)是一个地址,我们如何才能得到这个整数,而不使用inet函数。
j7dteeu81#
将字符串扫描成四个字节,并将它们相加/移位成32位整数。
dfddblmv2#
Posix.1-2001为此任务提供了inet_pton()。这也有几个ms-windows版本。
inet_pton()
nfg76nw03#
//No checking of the input unsigned int c1,c2,c3,c4; scanf("%d.%d.%d.%d",&c1,&c2,&c3,&c4); unsigned long ip = (unsigned long)c4+c3*256+c2*256*256+c1*256*256*256; printf("The unsigned long integer is %lu\n",ip);
**编辑:**对于那些对生成的代码感兴趣的人,GCC足够聪明,可以用左移来代替我的256乘法。(在我的程序中,我也称之为exit):
0x80483d4 <main>: lea 0x4(%esp),%ecx 0x80483d8 <main+4>: and $0xfffffff0,%esp 0x80483db <main+7>: pushl -0x4(%ecx) 0x80483de <main+10>: push %ebp 0x80483df <main+11>: mov %esp,%ebp 0x80483e1 <main+13>: push %ecx 0x80483e2 <main+14>: sub $0x34,%esp 0x80483e5 <main+17>: lea -0x14(%ebp),%eax 0x80483e8 <main+20>: mov %eax,0x10(%esp) 0x80483ec <main+24>: lea -0x10(%ebp),%eax 0x80483ef <main+27>: mov %eax,0xc(%esp) 0x80483f3 <main+31>: lea -0xc(%ebp),%eax 0x80483f6 <main+34>: mov %eax,0x8(%esp) 0x80483fa <main+38>: lea -0x8(%ebp),%eax 0x80483fd <main+41>: mov %eax,0x4(%esp) 0x8048401 <main+45>: movl $0x8048520,(%esp) 0x8048408 <main+52>: call 0x8048320 <scanf@plt> 0x804840d <main+57>: mov -0x8(%ebp),%eax 0x8048410 <main+60>: mov %eax,%edx 0x8048412 <main+62>: shl $0x8,%edx 0x8048415 <main+65>: mov -0xc(%ebp),%eax 0x8048418 <main+68>: lea (%edx,%eax,1),%eax 0x804841b <main+71>: mov %eax,%edx 0x804841d <main+73>: shl $0x8,%edx 0x8048420 <main+76>: mov -0x10(%ebp),%eax 0x8048423 <main+79>: lea (%edx,%eax,1),%eax 0x8048426 <main+82>: mov %eax,%edx 0x8048428 <main+84>: shl $0x8,%edx 0x804842b <main+87>: mov -0x14(%ebp),%eax 0x804842e <main+90>: lea (%edx,%eax,1),%eax 0x8048431 <main+93>: mov %eax,-0x18(%ebp) 0x8048434 <main+96>: mov -0x18(%ebp),%eax 0x8048437 <main+99>: mov %eax,0x4(%esp) 0x804843b <main+103>: movl $0x804852c,(%esp) 0x8048442 <main+110>: call 0x8048330 <printf@plt> 0x8048447 <main+115>: movl $0x0,(%esp) 0x804844e <main+122>: call 0x8048340 <exit@plt>
wlp8pajw4#
uint32_t getDecimalValueOfIPV4_String(const char* ipAddress) { uint8_t ipbytes[4]={}; int i =0; int8_t j=3; while (ipAddress+i && i<strlen(ipAddress)) { char digit = ipAddress[i]; if (isdigit(digit) == 0 && digit!='.'){ return 0; } j=digit=='.'?j-1:j; ipbytes[j]= ipbytes[j]*10 + atoi(&digit); i++; } uint32_t a = ipbytes[0]; uint32_t b = ( uint32_t)ipbytes[1] << 8; uint32_t c = ( uint32_t)ipbytes[2] << 16; uint32_t d = ( uint32_t)ipbytes[3] << 24; return a+b+c+d; }
brqmpdu15#
inet_pton()最小可运行示例
提及地点:https://stackoverflow.com/a/34077884/895245,但这里有一个改编自man inet_pton的例子:pton.c
man inet_pton
#include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { struct in_addr addr; int s; if (argc != 2) { exit(EXIT_FAILURE); } s = inet_pton(AF_INET, argv[1], &addr); if (s <= 0) { if (s == 0) fprintf(stderr, "Not in presentation format"); else perror("inet_pton"); exit(EXIT_FAILURE); } printf("0x%08x\n", ntohl(addr.s_addr)); exit(EXIT_SUCCESS); }
编译:
gcc -o pton.out pton.c
运行:
./pton.out 192.187.1.42
输出:
0xc0bb012a
因此,我们看到字符串被转换为整数,例如:
来自man inet_pton的相关报价比较不同选项:与inet_aton(3)和inet_addr(3)不同,inet_pton()支持IPv6地址。另一方面,inet_pton()只接受点十进制表示法的IPv4地址,而in‐ et_aton(3)和inet_addr(3)允许更通用的数字和点表示法(十六进制和八进制数字格式,以及不需要显式写入所有四个字节的格式)。有关以数字和点表示法处理IPv6地址和IPv4地址的接口,请参见getaddrinfo(3)。在Ubuntu 23.04上测试。
5条答案
按热度按时间j7dteeu81#
将字符串扫描成四个字节,并将它们相加/移位成32位整数。
dfddblmv2#
Posix.1-2001为此任务提供了
inet_pton()
。这也有几个ms-windows版本。nfg76nw03#
**编辑:**对于那些对生成的代码感兴趣的人,GCC足够聪明,可以用左移来代替我的256乘法。(在我的程序中,我也称之为exit):
wlp8pajw4#
brqmpdu15#
inet_pton()
最小可运行示例提及地点:https://stackoverflow.com/a/34077884/895245,但这里有一个改编自
man inet_pton
的例子:pton.c
编译:
运行:
输出:
因此,我们看到字符串被转换为整数,例如:
来自
man inet_pton
的相关报价比较不同选项:与inet_aton(3)和inet_addr(3)不同,inet_pton()支持IPv6地址。另一方面,inet_pton()只接受点十进制表示法的IPv4地址,而in‐ et_aton(3)和inet_addr(3)允许更通用的数字和点表示法(十六进制和八进制数字格式,以及不需要显式写入所有四个字节的格式)。有关以数字和点表示法处理IPv6地址和IPv4地址的接口,请参见getaddrinfo(3)。
在Ubuntu 23.04上测试。