I tried the following code as a naive attempt to implement swapping of R
and B
bytes in an ABGR
word
#include <stdio.h>
#include <stdint.h>
uint32_t ABGR_to_ARGB(uint32_t abgr)
{
return ((abgr ^= (abgr >> 16) & 0xFF) ^= (abgr & 0xFF) << 16) ^= (abgr >> 16) & 0xFF;
}
int main()
{
uint32_t tmp = 0x11223344;
printf("%x %x\n", tmp, ABGR_to_ARGB(tmp));
}
To my surprise this code "worked" in GCC in C++17 mode - the bytes were swapped
http://coliru.stacked-crooked.com/a/43d0fc47f5539746
But it is not supposed to swap bytes! C++17 clearly states that the RHS of assignment is supposed to be [fully] sequenced before the LHS, which applies to compound assignment as well. This means that in the above expression each RHS of each ^=
is supposed to use the original value of abgr
. Hence the ultimate result in abgr
should simply have B
byte XORed by R
byte. This is what Clang appears to produce (amusingly, with a sequencing warning)
http://coliru.stacked-crooked.com/a/eb9bdc8ced1b5f13
A quick look at GCC assembly
reveals that it seems to sequence it backwards: LHS before RHS. Is this a bug? Or is this some sort of conscious decision on GCC's part? Or am I misunderstanding something?
P0145R3
is supported in 7 and the release notes agree as well. They at least got the more obvious cases fixed. Clang and MSVS seem to do the right thing – Isleeng++ -Wall
. – Publicationint x = 1; (x *= (x+3)) *= (x+7);
It elicits the same warnings from both compilers and produces different results. – n.m. 5 mins ago – Publication