Я попробовал следующий код как наивную попытку реализовать замену байтов 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));
}
К моему удивлению, этот код "работал" в GCC в режиме C ++ 17 - байты поменялись местами
http://coliru.stacked-crooked.com/a/43d0fc47f5539746
Но поменять местами байты не предполагается! В C ++ 17 четко указано, что RHS присваивания должен быть [полностью] упорядочен перед LHS, что также применимо к составному присваиванию. Это означает, что в приведенном выше выражении предполагается, что каждая правая часть каждого ^=
использует исходное значение abgr
. Следовательно, конечный результат в abgr
должен просто иметь B
байтов, соединенных с помощью XOR на R
байтов. Это то, что, кажется, производит Clang (что забавно, с предупреждением о последовательности)
http://coliru.stacked-crooked.com/a/eb9bdc8ced1b5f13
Быстрый взгляд на сборку GCC
показывает, что он, кажется, упорядочивает его в обратном порядке: LHS перед RHS. Это ошибка? Или это какое-то осознанное решение со стороны GCC? Или я что-то недопонимаю?
P0145R3
поддерживается в версии 7 и примечания тоже согласны. По крайней мере, они исправили более очевидных случаев. Clang и MSVS , похоже, поступают правильно - person Shafik Yaghmour   schedule 25.07.2018g++ -Wall
. - person n. 1.8e9-where's-my-share m.   schedule 25.07.2018int x = 1; (x *= (x+3)) *= (x+7);
. Оно вызывает одинаковые предупреждения от обоих компиляторов и дает разные результаты. - н.м. 5 минут назад - person n. 1.8e9-where's-my-share m.   schedule 25.07.2018