Вот как я об этом думаю.
->
и .
на самом деле не являются инфиксными операторами.Их правая часть не является выражением: если x.y
и x->y
допустимы, то также (x).y
и (x)->y
, но вы не можете написать x.(y)
или x->(y)
.Правая часть всегда является простым идентификатором, а не общим выражением.
Вот почему я называю .
и ->
операторы мета-постфикса: для каждого идентификатора foo
, .foo
и ->foo
являются постфиксными операторами.
Общее правило приоритета операторов в C состоит в том, что постфиксные операторы имеют наивысший приоритет, за ними следуют префиксные операторы, за которыми следуют инфиксные операторы.
Ваше выражение,
(uint32 *)&b->c.d
имеет два префиксных оператора ((uint32 *)
и &
) и два постфиксных оператора (->c
и .d
).(Приведения (в форме ( TYPE ) EXPR
) также являются префиксными операторами.) Поскольку постфикс префикс префикса, мы можем заключить его в скобки как
(uint32 *)(&((b->c).d))
, который оценивается следующим образом:
- Возьмите значение
b
, которое должно быть указателем на структуру или объединение. - Разыщите его и получите поле
c
, которое само должно быть структурой или объединением. - Получите поле
d
. - Возьмите его адрес.
- Приведите адрес к
uint32 *
.