4 ms·
Also probably excusable because 2010, but from that same part of the article: void swap(int& x, int& y); void swap(float& x, float& y) { swap(
by stncls 4y ago
Also probably excusable because 2010, but from that same part of the article:
void swap(int& x, int& y);
void swap(float& x, float& y) {
swap((int&)x, (int&)y);
}
This is UB and may explode. Probably the only portable way to do it is a memcpy() [1].
[1] https://blog.regehr.org/archives/959 https://blog.regehr.org/archives/959
- CyberRabbi 4y agoC compilers should really refuse to compile code that does blatant type punning like this. Is there a book out there that is teaching people this is okay? Everything I’ve ever learned about C/C++ has explicitly warned against type punning.
- wallaBBB 4y agoLow level embedded begs to differ
- wheybags 4y agoWell, reality is many real world projects depend on it. Eg linux, disables strict aliasing. IMO the strict aliasing rule is a mistake, people know how the code should behave, so it should behave as expected.
- josefx 4y ago> MO the strict aliasing rule is a mistake, people know how the code should behave, so it should behave as expected. The strict aliasing rule exists because without it a C compiler has to second guess every load and store, which would have been horribly slow in the 80s and would be even worse now. It still ends up doing that for distinct pointers with the same type, which is why you can explicitly restrict them in newer language versions so the compiler can assume that those pointers wont alias.
- wheybags 4y agoWell the linux ptoject does just fine without strict aliasing based optimisations. Pretty much everything on windows is built with msvc, which doesn't depend on strict aliasing for optimisation either.
- CyberRabbi 4y agoLinux also depends on GCC or compilers that share its behavior w.r.t. type aliasing.
- tsimionescu 4y agoEDIT: the example below is valid, but it neither swaps the pointers, nor does it avoid extra registers/stack usage; and there is no way to use Unions to achieve this, even in C, as calling `swapI(&(((union swappable*)x)->i), &(((union swappable*)y)->i))` is UB. The best way to do this in C (NOT C++) would be with unions, assuming you know the size of int and float for your platform. The following would be valid C: union swappable{ float f; int i; } void swapF(float* x, float* y) { swappable xs, ys; xs.f = *x; ys.f = *y; swapI(&xs.i, &ys.i); } Given that they are using overloaded functions though, we're in C++ land where there is no correct way to achieve it (or maybe you could with char*, as that is allowed to alias?).
- OskarS 4y agoThe best way to do this in C++ is using std::bit_cast, which unfortunately only became available in C++20. Before that, you have to memcpy. That works just fine, but the syntax is a bit clunky and it doesn’t work in constexpr contexts, which is why std::bit_cast was introduced. Compilers will optimize all of this to the same machine code.
- unnah 4y agoInteresting... I thought for sure that would be undefined behaviour like in C++, but apparently it has been defined since C99: https://en.cppreference.com/w/c/language/union https://en.cppreference.com/w/c/language/union
- sltkr 4y agoThat code doesn't even swap the floats.