Стандарт упоминает е (а, (т = 3, T + 2), в); в соответствии с моим пониманием это будет выражение присваивания, за которым следует выражение для второго оператора.
Но грамматика перечисляет это рядом:
выражение:
Назначение выражение
выражение, присваивание-выражение
Рабочий проект, Стандарт для программирования
Язык С
++ Редакция N4140 (ноябрь 2014 г.)
Кто-то такой хороший, чтобы объяснить мне, пожалуйста, что я здесь скучаю?
Когда ты видишь
expression: assignment-expression expression, assignment-expression
Это означает, что есть 2 возможности для выражения. Одна возможность, что это просто assignment-expression
это определено где-то ранее. Или это рекурсивно представляется как expression, assignment-expression
Таким образом, после его расширения вы получите, что выражение является разделенным запятыми списком одного или нескольких токенов присваивания-выражения.
В примере, который вы упомянули, вторым параметром является выражение (t = 3, t + 2), которое состоит из 2-х разделенных запятыми выражений-присваиваний — и так как оно появляется «В контекстах, где запятая задается специальным значением« это должно »» появляются только в скобках «.
Чтобы выяснить, почему присваивание-выражение может принимать форму t + 2, вы должны вернуться к его определениям и всегда выбирать первый выбор.
assignment-expression
-> conditional-expression
--> logical-or-expression
---> logical-and-expression
----> inclusive-or-expression
-----> exclusive-or-expression
------> and-expression
-------> equality-expression
--------> relational-expression
---------> shift-expression
----------> additive-expression - this is what you see
Это синтаксическая нотация (см. §1.6 N4140).
Он в основном используется для оценки приоритета, но название может вводить в заблуждение.
Например, в [expr.ass] (§5.18) у вас есть следующее определение:
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expression
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=
Так что assignment-expression
может быть conditional-expression
или throw-expression
даже если ни один не выполняет какое-либо задание.
Это просто утверждает, что a = b
, throw 10
или же cond ? c : d
являются выражениями с одинаковым порядком приоритета.
Обратите внимание, что с момента определения выражение является
выражение:
Назначение выражение
выражение
,
Назначение выражение
вторая строка означает, что любой Назначение выражение можно считать выражение, вот почему t=3, t+2
является допустимым выражением.
Так почему же грамматика такая? Прежде всего обратите внимание, что грамматика для выражений строится по шагам из наиболее тесно связанной категории первичное выражение до наименее тесно связанной категории выражение. (А потом то что(
выражение )
» это первичное выражение переводит грамматику выражения в полный круг и позволяет сделать любое выражение более тесно связанным, чем все, что его окружает, добавив скобки.)
Например, общеизвестный факт, что двоичный *
связывает сильнее, чем двоичный +
следует из этих частей грамматики:
мультипликативный выражение:
м-выражение
мультипликативный выражение
*
м-выражениемультипликативный выражение
/
м-выражениемультипликативный выражение
%
м-выражениеДобавка-выражение:
мультипликативный выражение
Добавка-выражение
+
мультипликативный выражениеДобавка-выражение
-
мультипликативный выражение
В выражении 2 + 3 * 4
, литералы 2
, 3
, а также 4
можно считать м-выражение, или, следовательно, также мультипликативный выражение или же Добавка-выражение. Так что вы можете сказать 2 + 3
будет квалифицироваться как Добавка-выражение, но это не мультипликативный выражение, так что полный 2 + 3 * 4
не могу так работать. Вместо грамматических сил 3 * 4
считаться мультипликативный выражение, чтобы 2 + 3 * 4
может быть Добавка-выражение. Следовательно 3 * 4
является подвыражением двоичного +
,
Или в выражении 2 * 3 + 4
, 3 + 4
можно считать Добавка-выражение, но тогда это не м-выражение, так что это не работает. Вместо этого парсер должен признать, что 2 * 3
это мультипликативный выражение, который также является Добавка-выражение, так 2 * 3 + 4
является действительным Добавка-выражение, с 2 * 3
как подвыражение двоичного +
,
Рекурсивный характер большинства грамматических определений имеет значение, когда один и тот же оператор используется дважды или два оператора с одинаковым приоритетом.
Возвращаясь к грамматике запятой, если у нас есть токены «a, b, c
«Можно сказать, b, c
может быть выражение, но это не Назначение выражение, так b, c
не может быть подвыражением целого. Вместо этого грамматика требует признания a, b
как выражение, который допускается как левое подвыражение другого оператора запятой, так a, b, c
также выражение с a, b
как левый операнд.
Это не имеет никакого значения для встроенной запятой, так как ее значение является ассоциативным: «оценивать и отбрасывать a
, тогда значение результата получается из оценки (оценить и отбросить b
, тогда значение результата получается из оценки c
) «делает так же, как» оценивать и отбрасывать (оценивать и отбрасывать a
, тогда значение результата получается из оценки b
), то значение результата получается из оценки c
».
Но это дает нам четко определенное поведение в случае перегрузки operator,
, Дано:
struct X {};
X operator,(X, X);
X a, b, c;
X d = (a, b, c);
мы знаем, что последняя строка означает
X d = operator,(operator,(a,b), c);
и не
X d = operator,(a, operator,(b,c));
(Я бы посчитал особенно вредным определение неассоциативной operator,
, но это разрешено.)
f(a,(t=3,t+2),c);
Здесь, во-первых, магазины 3
в t
переменная, затем вызывает функцию f()
с тремя аргументами. Это означает, что значение второго аргумента становится 5
и перейти к функции.