У меня есть следующий код, который я прочитываю:
if( (i%2) == 0 ){
*d = ((b & 0x0F) << 4);
}
else{
*d++ |= (b & 0x0F);
};
Я смотрю конкретно на else
оператор и задающийся вопросом в том, какой порядок это происходит? У меня нет регулярного компилятора C, таким образом, я не могу протестировать это. Когда мы выполняем *d++ |= (b & 0x0F);
, в каком порядке это происходит?
++ применяется к указателю d
, а не к присвоенному значению l, * d
.
Если вы действительно хотите, вы можете думать об этом так:
b
- побитовое И: ed с константой 0x0f
d
. d
увеличивается до следующего значения. ++
произойдет до | =
. Операторы присваивания находятся внизу диаграммы приоритета.
Согласно http://www.cppreference.com/wiki/operator_precedence
он оценит (b & 0x0F), затем применит | = к нему и назначит его * b, наконец, увеличивает значение, на которое указывает * b.
Выражение * d ++ | = (b & 0x0F)
распадается следующим образом:
* d ++
и b & 0x0F
каждый раз оценивается (порядок, в котором они оцениваются, не указан; компилятор может оценить b & 0x0F
до * d ++
, поскольку результат не зависят от порядка, в котором происходит вычисление); (b & 0x0F)
побитовый или с результатом * d ++
; d
обновляется. Выражение * d ++
анализируется как * (d ++)
; т.е. вы разыменовываете результат выражения d ++
. Выражение d ++
оценивается как текущее значение d
и в некоторой неуказанной точке перед следующей точкой последовательности (в данном случае концом оператора) , значение d
обновляется. Побочный эффект обновления d
не должен применяться немедленно; это может произойти до или после задания.
Сначала выполняется правая часть | =
, затем выполняется присвоение * d | =
, затем d
увеличивается. Обычно, когда у вас есть код, который вызывает подобные вопросы, вы должны просто переписать его для ясности.
++
. Однако пост-инкремент (т.е. d++
здесь) эквивалентен этому (temp=d, d++, temp)
.
d++ возвращает значение d, которое было до его увеличения. Затем оно разыменовывается *, и именно на это место выполняется |=. Таким образом, данные в месте перед инкрементом d будут содержать (b & 0x0F).
В общем, если порядок операций в строке кода не ясен с первого взгляда, рефакторите строку на составляющие ее операции, пока они не станут ясными. Сгенерированный код не становится быстрее или компактнее только от того, что в одну строку языка Си втиснуто много операций! Нет никаких веских причин жертвовать понятностью таким образом. Замените строку на
*d |= (b & 0x0F);
d++;