Этот точный пример описан в черновом стандарте C99 ( те же подробности в C11 ) 6.4 Лексические элементы, параграф 4 , в котором говорится:
Если входной поток был проанализирован в токены предварительной обработки до заданного символа, следующий токен предварительной обработки - это самая длинная последовательность символов, которая может составлять токен предварительной обработки.[...]
, также известное как правило максимального жаворонка , которое используется в лексическом анализе, чтобы избежать неясностей и работает, беря столько элементов, сколько возможно, чтобысформируйте действительный токен.
параграф также имеет два примера, второй является точным соответствием вашему вопросу и выглядит следующим образом:
ПРИМЕР 2 Фрагмент программы x +++++ y анализируется как x ++ ++ + y, что нарушает ограничение на операторы приращения, даже если синтаксический анализ x ++ + ++ y может привести к правильному выражению.
, который сообщаетнам, что:
a+++++b
будет проанализирован как:
a ++ ++ + b
, что нарушает ограничения на пост-инкремент, так как результатом первого пост-инкремента является rvalue, а пост-инкремент требует lvalue,Это описано в разделе 6.5.2.4
Операторы приращения и уменьшения постфикса , в которых говорится ( выделение шахты ):
Операнд оператора увеличения или уменьшения постфиксадолжен иметь квалифицированный или неквалифицированный вещественный или указательный тип, а должен быть изменяемым lvalue.
и
Результат оператора postfix ++ равензначение операнда.
Книга C ++ Gotchas также охватывает этот случай в Gotcha #17
Максимальные проблемы Мунка такая же проблема в C ++ , а также приводит несколько примеров.Это объясняет, что при работе со следующим набором символов:
->*
лексический анализатор может выполнять одно из трех действий:
- Обрабатывать его как три токена:
-
,>
и *
- Считайте его двумя токенами:
->
и *
- Считайте его одним токеном:
->*
Правило maxim munch позволяет избежать этих двусмысленностей.Автор указывает, что он ( В контексте C ++ ):
решает гораздо больше проблем, чем вызывает, но в двух распространенных ситуациях это раздражает.
Первым примером будут шаблоны, аргументы шаблона которых также являются шаблонами (, который был решен в C ++ 11 ), например:
list<vector<string>> lovos; // error!
^^
Что интерпретирует закрывающие угловые скобки как оператор сдвига , и поэтому для устранения неоднозначности требуется пробел:
list< vector<string> > lovos;
^
Во втором случае используются аргументы по умолчанию для указателей, например:
void process( const char *= 0 ); // error!
^^
будет интерпретироваться как *=
оператор присваивания, решение в этом случае заключается в именовании параметров в объявлении.