Чому граматика BNF C допускає декларації з порожньою послідовністю init-деклараторів?


28

Переглядаючи граматику BNF C, я подумав, що дивно, що виробниче правило для декларації виглядає таким чином (згідно https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ):

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

Навіщо використовувати *кількісний коефіцієнт (що означає нуль або більше подій) для init-declarator? Це дозволяє твердженням, таким як int;або void;бути синтаксично дійсними, навіть якщо вони семантично недійсні. Чи не могли вони просто використати +кількісний коефіцієнт (одне або кілька подій) замість *правила виробництва?

Я спробував скласти просту програму, щоб побачити, що видає компілятор, і все, що він робить, - це попередження.

Вхід:

int main(void) {
    int;
}

Вихід:

test.c: In function main’:
test.c:2:5: warning: useless type name in empty declaration
     int;
     ^~~

2
Різниця полягає в тому, що BNF визначає лише синтаксис. Дуже багато речей дозволено, але все-таки недійсні (або абсурдні) C. Хоча приємна знахідка!
larkey

7
Ну, і будь ласка, використовуйте intяк тип повернення для, mainа не використовуйте ()як список типів параметрів у функціях, а (void)замість цього.
larkey

1
Концептуально в цьому немає нічого поганого, окрім того, що це звучить дещо смішно: це, головним чином, запитання комп’ютера: "Я хотів би нульових змінних int, будь ласка, імен: [порожній набір].". Зрештою, можна попросити когось нульових яблук (хоча це, ймовірно, викликає трохи цікавішу реакцію, ніж просити його, але це не є суттєвим безглуздим твердженням). Отже, чому це має бути неграматично в С? У цьому граматиці немає нічого поганого.
The_Sympathizer

Дуже часто речі працюють набагато приємніше, якщо ми все-таки включимо вакуумний (а може бути, вакуумний) корпус?
The_Sympathizer

Іноді не людина пише програму, а іншу програму. Така програма іноді може захотіти надрукувати "int" з подальшим комою списком про потрібні нам імена, а потім ";" і нехай вам не потрібно перевіряти, чи спочатку цей список порожній.
Хаген фон Ейтцен

Відповіді:


29

declaration-specifierвключає type-specifier, що включає enum-specifier. Така конструкція

enum stuff {x, y};

є дійсним declarationз ні init-declarator.

Такі конструкції int;виключаються через граматичні обмеження :

Декларація, відмінна від статичної_запис декларації, повинна оголошувати щонайменше декларатор (крім параметрів функції або членів структури чи об'єднання), тег або членів перерахування.

Я б здогадувався, що за тим, що ваш компілятор видає попередження, є причини зворотної сумісності.


14

Декларація без декларатора init:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

нешкідливий для списків специфікаторів декларації, які не є єдиним enum/ struct/ unionспецифікатором, і він корисно відповідає тим, що є.

У будь-якому випадку, представлена ​​граматика також буде помилково відповідати деклараціям типу « int struct foo x;або» double _Bool y;(це дозволяє декілька специфікаторів для відповідності подібним речам long long int), але все це можна буде виявити пізніше, в семантичній перевірці.

Сама граматика BNF не відкидає всіх незаконних конструкцій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.