Таблица приоритетов оператора C ++ из http://en.cppreference.com/w/cpp/language/operator_precedence (Я знаю, что это не нормативно, но стандарт не говорит о приоритетности или ассоциативности) помечает унарные операторы как правые / левые ассоциативные.
От обсуждения другого вопроса у меня остались сомнения. Имеет ли смысл унарные операторы быть ассоциативными?
Это просто артефакт того, как ассоциативность получена из грамматики.
причина это дополнение левоассоциативно в том, что одно из произведений для Добавка-выражение является Добавка-выражение + мультипликативный выражение, с аддитивным выражением слева. Итак, когда вы видите:
a + b + c
это должно быть эквивалентно (a + b) + c
потому что единственный способ сопоставить производство с a + b
как Добавка-выражение а также c
как мультипликативный выражение. a
сам по себе является Добавка-выражение, но b + c
это не мультипликативный выражение так что a + b + c
не соответствует производству, если мы пытаемся взять a
как Добавка-выражение.
Если вы еще этого не сделали, я рекомендую вам прочитать главу «Выражения», игнорируя семантику: посмотрите только на грамматические произведения. Тогда вы увидите только как это то, что приоритет и ассоциативность определяются грамматикой. Большая хитрость в том, что каждый тип выражения с «высоким приоритетом» IS-A тип выражения «с низким приоритетом». Так что каждый мультипликативный выражение является Добавка-выражение, но не наоборот, и это то, что делает умножение «связывать крепче», чем сложение.
Префиксные унарные операторы определены в грамматике следующим образом: Унарное выражение: ++ монолитно-выражение и так далее, с оператором слева для префикса и справа для постфикса. Другими словами, мы «вставляем скобки» слева для постфикса и справа для префикса. То есть мы можем сказать, что группировка слева направо для постфиксных операторов и справа налево для префиксных операторов. И действительно, стандарт C ++ говорит именно об этом (5.2 / 1 и 5.3 / 1 в C ++ 03). Это может быть злоупотребление терминологией или, по крайней мере, новая чеканка, обозначающая эту унарную группировку как «ассоциативность». Но это не главное, так как очевидно, что нужно иметь в виду.
Единственное отличие здесь между бинарными и унарными операторами состоит в том, что синтаксис все еще имеет смысл, если бинарные операторы сгруппированы в противоположном направлении, поэтому a - b - c
средства a - (b - c)
, Это было бы удивительно, но никак не повлияло бы на язык. С унарными операторами было бы более чем удивительно группировать !!a
как (!!)a
язык также должен был бы предоставить имея в виду для под-выражения !!
, которого в настоящее время нет. Функциональный язык может придать этому значение: !!
может означать функцию, состоящую из !
а также !
то есть та же операция, что и static_cast<bool>()
, но C ++ не имеет понятия составления функций или операторов. Причина, по которой С ++ не нужно указывать это значение, заключается в том, что !
«группы справа налево». Который (из-за большого трюка в грамматике) является просто еще одним способом сказать, что !!
не является синтаксически правильным выражением, поэтому никогда не является подвыражением чего-либо.
Так что да, это делает Имеет смысл сказать, что префиксные операторы группируются справа налево, а постфиксные операторы — слева направо. Но также «очевидно», что так должно быть, из-за других вещей, которые мы знаем о языке C ++.
Кстати, я думаю, что технически говоря на C ++, по крайней мере, postfix ++
является не унарный оператор. Это постфиксный оператор. Но это на самом деле не имеет значения, за исключением того, что это терминология в стандарте, потому что, очевидно, это оператор и у него есть один операнд, поэтому он «унарный» в английском языке.
Ассоциативность оператора в случае унарных операторов просто определяет, на какой стороне операнда появляется оператор.
Рассмотрим следующий фрагмент кода
int *p;
*p++;
Выражение *p++
можно оценить как (*p)++
(увеличивая объект, на который указывает p) или *(p++)
(указывая на следующий объект, указанный p).
Поскольку унарные операторы ассоциативны справа, выражение *p++
будет оцениваться как *(p++)
, (Я придумал это во время чтения Керниган и Ричи.)
Кажется, что приоритет и ассоциативность были изменены и постфикс ++
имеет более высокий приоритет, чем разыменование *
оператор.
Согласно C11 вышеупомянутое выражение будет оцениваться как *(p++)
,
Я надеюсь, что это делает более понятным, почему унарные операторы имеют ассоциативность.
Благодаря Люциан Григоре за указание на это.
Не уверен, но если следующее было верно, да.
++i--
а как нет и выкидывает ошибку
lvalue required as increment operand
Все поведение унарного оператора можно объяснить только с точки зрения приоритета.