Цей точний приклад висвітлений у проекті стандарту C99 (ті самі подробиці в C11 ), розділ 6.4, пункт 4 лексичних елементів, де сказано:
Якщо вхідний потік був проаналізований на маркери попередньої обробки до заданого символу, наступним маркером попередньої обробки є найдовша послідовність символів, яка може становити маркер попередньої обробки. [...]
що також відоме як правило максимального обману, яке використовується в лексичному аналізі, щоб уникнути двозначностей, і працює, беручи якомога більше елементів, щоб сформувати дійсну лексему.
абзац також має два приклади, другий - це точна відповідність вашому запитанню, та такий:
ПРИКЛАД 2 Фрагмент програми x +++++ y аналізується як x ++ ++ + y, що порушує обмеження на оператори приросту, хоча аналіз x ++ + ++ y може дати правильний вираз.
що говорить нам, що:
a+++++b
буде проаналізовано як:
a ++ ++ + b
що порушує обмеження на приріст повідомлення, оскільки результат першого збільшення посту є значенням r, а для збільшення розміру потрібне значення lvalue. Це висвітлено в розділі 6.5.2.4
Оператори приросту та зменшення Postfix, де сказано ( наголос мій ):
Операнд оператора збільшення або зменшення постфікса повинен мати кваліфікований або некваліфікований дійсний тип або тип вказівника і повинен бути змінним значенням l.
і
Результатом оператора postfix ++ є значення операнда.
Книга C ++ Gotchas також висвітлює цей випадок у програмі " Gotcha #17
Максимальні проблеми Мунка". Це та сама проблема в C ++ , а також містить кілька прикладів. Це пояснює, що коли йдеться про наступний набір символів:
->*
лексичний аналізатор може зробити одне з трьох речей:
- Розглядайте це як три лексеми:
-
, >
і*
- Розгляньте це як два лексеми:
->
і*
- Розгляньте це як один знак:
->*
Максимальна жують правило дозволяє уникнути цих неясностей. Автор зазначає, що це ( у контексті C ++ ):
вирішує набагато більше проблем, ніж викликає, але в двох типових ситуаціях це дратує.
Першим прикладом можуть бути шаблони, аргументи шаблону яких також є шаблонами ( що було вирішено в C ++ 11 ), наприклад:
list<vector<string>> lovos;
^^
Що трактує кутові дужки закриття як оператор зсуву , і тому потрібен простір для неоднозначності:
list< vector<string> > lovos;
^
Другий випадок включає аргументи за замовчуванням для покажчиків, наприклад:
void process( const char *= 0 );
^^
інтерпретується як *=
оператор присвоєння, рішення в цьому випадку полягає у назві параметрів у декларації.