
On 09/09/2011 10:45 AM, Beman Dawes wrote:
I'm missing something. Could you please post the full function, without any preprocessing statements, where the aliasing issue is arising? I should have provided more context. Sorry about that. It was an addition to the body of the byteswap function in Phil's test code that sparked this whole performance discussion. With all the various byteswap implementations stripped away, the code becomes:
#include <cstdint> #include <iostream> #include <boost/endian/integers.hpp> using std::uint32_t; using namespace boost::endian; static inline uint32_t byteswap(uint32_t src) { return *reinterpret_cast<const ubig32_t*>(&src); } int main() { uint32_t s = 0; for (uint32_t i = 0; i < 1000000000; ++i) s += byteswap(x[i]); std::cout << s << "\n"; } I did this to compare timing of your endian<> class to your reorder functions, and to show that the former was considerably more efficient than the latter and that you could just implement reorder() in terms of endian<> using the reinterpret_cast above. I don't fully grasp the C++ aliaising rules, but Matt claims the above reinterpret_cast can (or does) result in undefined behavior. In this particular case, gcc doesn't complain about any aliasing problems and it does produce the correct answer, but that doesn't mean my code is correct. Oddly enough, when I used a trick I've used in the past to get rid gcc aliasing warnings, gcc started complaining the I had aliasing problems in some cases, so clearly I *really* don't understand the aliasing rules in C++. The trick I used is to use a union, which I though was the recommended way to alias a chunk of memory to multiple types. I.e. template<typename DST, typename SRC> DST aliased_ptr_cast(DST dst) { union { SRC src; DST dst; } u; u.src = src; return u.dst; } inline uint32_t byteswap_big(uint32_t src) { return *aliased_ptr_cast<const ubig32_t*>(&src); } Using the above code, along with main() defined further up, the app compiles warning free and produces the correct answer on linux/intel/g++-4.4. If I change the type in the "aliased_ptr_cast" from ubig32_t to either ulittle32_t or unative32_t, I start getting aliasing warnings. I clearly have some learning to do.