R
とB
バイトのスワッピングをABGR
単語に実装する単純な試みとして、次のコードを試しました
#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));
}
驚いたことに、このコードは C++17 モードの GCC で「機能」しました - バイトがスワップされました
http://coliru.stacked-crooked.com/a/43d0fc47f5539746
しかし、バイトをスワップすることは想定されていません! C++17 では、代入の RHS が LHS の前に [完全に] シーケンスされることになっていることが明確に述べられており、これは複合代入にも適用されます。これは、上記の式で、それぞれの各 RHS が^=
の元の値を使用することになっていることを意味しますabgr
。したがって、最終的な結果は、abgr
単純にB
バイトごとに XOR されたR
バイトである必要があります。これは、Clang が生成するように見えるものです (面白いことに、シーケンスの警告が表示されます)。
http://coliru.stacked-crooked.com/a/eb9bdc8ced1b5f13
GCC アセンブリの概要
それが逆にシーケンスされているように見えることを明らかにします: RHS の前に LHS です。これはバグですか?それとも、これはGCC側のある種の意識的な決定ですか? それとも私は何かを誤解していますか?