Порядок операций в C. ++ vs | =, который происходит первым? - PullRequest
5 голосов
/ 19 мая 2010

У меня есть следующий код, который я читаю:

if( (i%2) == 0 ){ 
    *d = ((b & 0x0F) << 4); 
}
else{
    *d++ |= (b & 0x0F); 
};

Я специально смотрю на оператор else и задаюсь вопросом, в каком порядке это происходит? У меня нет обычного компилятора C, поэтому я не могу это проверить. Когда мы выполняем *d++ |= (b & 0x0F);, в каком порядке это происходит?

Ответы [ 8 ]

11 голосов
/ 19 мая 2010

++ применяется к указателю d, а не к назначаемому lvalue, *d.

Если вы действительно хотите, вы можете думать об этом так:

  1. Значение b поразрядно-И: редактируется с константой 0x0f
  2. Полученная битовая комбинация имеет битовое ИЛИ: устанавливается на значение, на которое указывает d.
  3. Указатель d увеличивается, чтобы указывать на следующее значение.
5 голосов
/ 19 мая 2010

d ++ возвращает значение d, которое было до его увеличения. Это тогда разыменовывается *, и это местоположение - то, на чем выполняется | =. Таким образом, данные в местоположении до увеличения d будут иметь в своем составе (b & 0x0F).

В общем, если порядок операций в строке кода с первого взгляда неясен, рефакторируйте строку в составляющие ее операции, пока она не станет. Сгенерированный код не становится быстрее или компактнее, просто помещая множество операций в одну строку C! Нет веских оснований жертвовать таким пониманием. Заменить строку на

*d |= (b & 0x0F); 
d++;
2 голосов
/ 19 мая 2010

++ произойдет до |=. Операторы присваивания находятся внизу таблицы приоритетов.

2 голосов
/ 19 мая 2010

Сначала выполняется правая часть |=, затем выполняется присвоение *d |=, затем увеличивается d. Обычно, когда у вас есть код, который вызывает подобные вопросы, вам просто нужно переписать его для ясности.

0 голосов
/ 19 мая 2010

Выражение *d++ |= (b & 0x0F) разбивается следующим образом:

  1. Выражения *d++ и b & 0x0F оцениваются по одному разу (порядок, в котором они вычисляются, не указан; компилятор может вычислять b & 0x0F до *d++, поскольку результат не зависит от порядка в котором происходит оценка);
  2. Результат (b & 0x0F) является побитовым или равен результату *d++;
  3. Результат побитовой операции или сохраняется в месте, изначально указанном d;
  4. В какой-то момент во всем этом значение d обновляется.

Выражение *d++ анализируется как *(d++); то есть вы разыменовываете результат выражения d++. Выражение d++ соответствует текущему значению d, и в некоторой неопределенной точке перед следующей точкой последовательности (в данном случае, в конце оператора) значение d равно обновлено. Побочный эффект обновления d не должен применяться немедленно; это может произойти до или после назначения.

0 голосов
/ 19 мая 2010

Согласно http://www.cppreference.com/wiki/operator_precedence

он оценивает (b & 0x0F), затем применяет к нему знак = и присваивает ему значение * b, наконец увеличивая значение, на которое указывает * b.

0 голосов
/ 19 мая 2010

++ делается первым. Однако постинкремент (т.е. d++ здесь) эквивалентен этому (temp=d, d++, temp).

0 голосов
/ 19 мая 2010

Эта ссылка (приоритет оператора C ++) должна дать вам ответ.

...