Andrew Haley wrote: > Evan Jones wrote: >> Rupert Wood wrote: >>> I don't know how to fight aliasing rules but as another approach you >>> could template the function instead, i.e. >>> >>> template<typename T> T* exchange(T** ptr, T* next); >>> >>> exchange<int>(&a, &v2); >>> >>> since you're using C++ here. >> I initially dismissed this solution since the implementation of exchange >> is either a typical swap using a temporary, a compare-and-swap sequence >> or a mutex, depending on various compilation options. I wanted to avoid >> including the implementation in the header to avoid a bunch of #ifdefs. >> However, your email made me try to avoid the warning with a template >> wrapper: >> >> >> template <typename T> >> T* exchange_template(T** ptr, T* next) { >> return reinterpret_cast<T*>( >> exchange(reinterpret_cast<void**>(ptr), next)); >> } >> >> ... >> >> exchange_template(&a, &v2); >> >> >> I don't understand why, but this compiles without warnings. It also >> avoids needing to look up the aliasing rules, and places the dangerous >> cast in a single location, so this seems like a better solution. >> >> I would still like to know if my original solution is "correct" or not, >> since it would be needed for C. > > We have no way to know, since you didn't provide us with the source of > exchange(), and that's where the aliasing violation, if any, would > occur. > > However, the answer is almost certainly no. I don't know why you're > trying to do something so simple in such a difficult way. If you really > want to do this in standard portable C, the easiest way is a macro: > > #define SWAP(TYPE, A, B) do { TYPE tmp = a; b = b; b = tmp; } while (0) Err, #define SWAP(TYPE, A, B) do { TYPE tmp = a; a = b; b = tmp; } while (0) > > You can't portably cast a pointer to an int* to a pointer to a void* > and then dereference the resulting pointers since the things they point > to might not even be the same size. The union hack will work on gcc, > though. > > Andrew. > >