我需要(或多或少)实时处理大量这些.我目前正在使用的方法不再削减它.
std::string parse_ipv4_address( const std::vector& data, int start ) { char ip_addr[16]; snprintf( ip_addr, sizeof(ip_addr), "%d.%d.%d.%d", data[start + 0], data[start + 1], data[start + 2], data[start + 3] ); return std::string( ip_addr ); } // used like this std::vector ip = { 0xc0, 0xa8, 0x20, 0x0c }; std::string ip_address = parse_ipv4_address( ip, 0 ); std::cout << ip_address << std::endl; // not actually printed in real code // produces 192.168.32.12
有更快的方法吗?如何?
注意!性能是这里的问题所以这个问题不重复.
以下是影响绩效的潜在候选人:
snprintf
需要解析格式字符串,并执行错误处理.要么花费时间,要么实现你不需要的功能.
std::string
在返回时构造对象是昂贵的.它将受控序列存储在freestore内存中(通常实现为堆内存),这在C++(和C)中分配成本有些高.
使用a std::vector
来存储4字节值会不必要地耗费资源.它也在freestore中分配内存.将其替换char[4]
为32位整数(uint32_t
).
由于您不需要printf
-family函数的多功能性,您可以完全删除它,并使用查找表.查找表由256个条目组成,每个条目保存字节值0到255的可视化表示.为了优化它,让LUT包含尾随.
字符.(需要特别注意,以解决字节序.我在这里假设小端.)
解决方案可能如下所示:1):
const uint32_t mapping[] = { 0x2E303030, // "000." 0x2E313030, // "001." // ... 0x2E343532, // "254." 0x2E353532 // "255." }; alignas(uint32_t) char ip_addr[16]; uint32_t* p = reinterpret_cast(&ip_addr[0]); p[0] = mapping[data[0]]; p[1] = mapping[data[1]]; p[2] = mapping[data[2]]; p[3] = mapping[data[3]]; // Zero-terminate string (overwriting the superfluous trailing .-character) ip_addr[15] = '\0'; // As a final step, waste all the hard earned savings by constructing a std::string. // (as an ironic twist, let's pick the c'tor with the best performance) return std::string(&ip_addr[0], &ip_addr[15]); // A more serious approach would either return the array (ip_addr), or have the caller // pass in a pre-allocated array for output. return ip_addr;
char*
到uint32_t*
不明确的行为.除非您的平台(编译器和操作系统)提供额外的保证以使其定义良好,否则请勿使用.