我目前正在代码库中工作,其中IPv4地址表示为u_int8
的指针。等于运算符的实现如下:
bool Ipv4Address::operator==(const u_int8 * inAddress) const
{
return (*(u_int32*) this->myBytes == *(u_int32*) inAddress);
}
这可能是禁食的解决方案,但它会导致GCC编译器警告:
ipv4address.cpp:65: warning: dereferencing type-punned pointer will break strict-aliasing rules
如何在不破坏严格别名规则且不丢失性能点的情况下正确重写比较?
我考虑使用memcmp
或此宏:
#define IS_EQUAL(a, b) \
(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
我认为宏是最快的解决方案。
你推荐什么?
更新的
我刚刚阅读了文章Squeezing performance out of memcmp usage,它解释了编译器(Visual Studio,但也许还有GCC)如何优化!memcmp(..)
调用。
答案 0 :(得分:10)
我会选择memcmp()
另外想想如果你的编译器没有内联memcmp(),你将遇到函数上下文切换
你确定你需要努力优化吗?您是否已经检查过您的程序大部分时间都在进行此类操作?
答案 1 :(得分:3)
您从GCC收到错误的原因是长度超过1个字节的任何内容都喜欢与对象大小的倍数对齐。 32位整数喜欢从32位边界开始。 char
变量(有符号,无符号或普通)可以位于任何字节边界上,例如3对于处理器的32位读取不起作用。
在您的情况下,对于4个字节(32位),调用memcmp
的开销可能比实际比较字节的代码要多。
试试这个:
bool Ipv4Address::operator==(const u_int8 * inAddress) const
{
return myBytes[0] == inAddress[0]
&& myBytes[1] == inAddress[1]
&& myBytes[2] == inAddress[2]
&& myBytes[3] == inAddress[3];
}
看妈妈,不使用this->
成员函数代码!
至于效率,这段代码可能在调用memcpy
并从中执行返回的同时执行(不执行memcpy
的内容)。这假设memcpy
没有内联。知道如何为通用和大型案例编写编译器库,我怀疑这个代码仍然比memcpy
的内联版本更小更快。虽然证据是打印两个版本的装配清单并进行比较。
修改强>
注意:将实现声明为内联或将代码放在类声明中,将比定义危险的宏更好。它将更安全并包含相同数量的代码。我喜欢内联方法版本,因为它更易读,更易于维护。