2017-02-22 11 views
-4
struct T{ double x}; 

В C это не создает проблем.Почему вывод `struct T {double x};` different в C и C++?

Но в C++, это дает следующее сообщение об ошибке компиляции:

expected ';' at end of member declaration.

+12

потому что они разные языки? –

+0

Мне нравятся такие причудливые вещи. Интересно, что в грамматике отличается? Я отметил «язык-юрист». – Bathsheba

+1

Мой VC 2008 (сборка C) говорит: «ошибка C2143: синтаксическая ошибка: отсутствует»; перед '}' " –

ответ

12

С C11, "Структура и накидные спецификаторов, синтаксис" (6.7.2.1/1):

STRUCT декларацию :
        спецификатор-спецификатор-лист-структуры описатель-лист opt;

Каждый элемент структуры заканчивается точкой с запятой. Ваше утверждение о том, что существует «проблема», не основано на том, что говорит спецификация C. Если ваш компилятор принимает такой код, он не является компилятором C, или вы не используете его правильно. (Некоторые компиляторы имеют настраиваемый уровень стандартов соответствия.)

+2

Справа сэр, но если вы можете добавить некоторые информация о том, почему компилятор не генерирует ошибку, это было бы хорошо. OP, похоже, ожидает, что это должна быть синтаксическая ошибка, но компилятор не генерирует никаких. Почему это? –

+2

В основном я спрашиваю, почему компилятор считает «без проблем», ? –

+1

@SouravGhosh: Я не знаю, какой дешевый компилятор вы выбрали - как я должен отвечать на этот вопрос? Используйте стандартный компилятор C. –

-3

Вообще, C язык любит точку с запятой гораздо больше, чем Pascal (Delphi). В вашем случае, C принимает struct T{ double x};, но C++ уже требует struct T{ double x;};

+1

Точка с запятой формально (в С) - оператор _terminator_. Он сигнализирует конец инструкции (или превращает, например, выражение в оператор). Другие языки используют оператор _separators_, поэтому, если инструкция не указана, разделитель может (или должен) быть опущен. В C их нельзя опустить. Бывают случаи, когда упущение все еще недвусмысленно, случаи, когда компилятор может помечать эту ошибку в качестве предупреждения. –

+0

Пол Огилви, спасибо, я имел в виду то же самое, ты сказал это лучше меня. Действительно, Паскалю требуется точка с запятой как разделитель, а не терминатор. Но вопрос был: почему ** C ** позволяет опустить точку с запятой в поле структуры? – Spectorsky

+1

Это не так. Компилятор должен был сгенерировать ошибку вместо предупреждения. Теперь код больше не переносится (если эти предупреждения не были решены). –

2

Why output of struct T{ double x}; different in C and C++?

Определение структуры примера плохо формируется как в C и C++.

C и C++ - разные языки, они используют разные синтаксические анализаторы (или любой компонент компилятора обнаруживает эту ошибку). Результат отличается от того, что люди принимали различные решения, когда они реализовали парсер компилятора C, чем были сделаны, когда был реализован парсер C++.

Latter решил сделать ошибку, первая из которых выдает просто предупреждение и успешно компилируется, несмотря на ошибку. Другой компилятор C также может отказаться от компиляции, а компилятор C++ может принять программу (пока она вызывает предупреждение).

+0

Я нахожу это очень плохим объяснением. Речь идет не о решениях, а о персах (по стандарту языка). –

+1

@PaulOgilvie в этом случае отличие нет * в этом случае. Ни один из языков не позволяет оставить точку с запятой в этом контексте. Оба языка требуют диагностического сообщения, когда программа плохо сформирована. Оба языка позволяют компилятору создавать программу в любом случае (расширение языка разрешено). Разработчик компилятора добирается, чтобы ** решить **, расширять ли язык и разрешать компиляцию, или нет. – user2079303

3

ССАГПЗ анализатор для грамматики C реализован as follows:

/* If no semicolon follows, either we have a parse error or 
    are at the end of the struct or union and should 
    pedwarn. */ 
    if (c_parser_next_token_is (parser, CPP_SEMICOLON)) 
    c_parser_consume_token (parser); 
    else 
    { 
     if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) 
    pedwarn (c_parser_peek_token (parser)->location, 0, 
     "no semicolon at end of struct or union"); 
     else if (parser->error 
      || !c_parser_next_token_starts_declspecs (parser)) 
    { 
     c_parser_error (parser, "expected %<;%>"); 
     c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); 
     break; 
    } 

     /* If we come here, we have already emitted an error 
    for an expected `;', identifier or `(', and we also 
     recovered already. Go on with the next field. */ 
    } 

Он вызывает функцию pedwarn на точку с запятой.

Определение pedwarn не найдено here. Он гласит:

  • pedwarn is for code that is accepted by GCC but it should be rejected or diagnosed according to the current standard, or it conflicts with the standard (either the default or the one selected by -std=). It can also diagnose compile-time undefined behavior (but not runtime UB). pedwarns become errors with -pedantic-errors .