Какова цель использования -pedantic в компиляторе GCC / G ++?

136

Эта записка говорит:

-ansi: указывает компилятору реализовать опцию языка ANSI. Это отключает определенные «функции» GCC, которые несовместимы со стандартом ANSI.

-pedantic: используется в сочетании с -ansi, это говорит компилятору строго придерживаться стандарта ANSI, отклоняя любой код, который не соответствует.

Перво-наперво:

  • Какова цель -pedanticи -ansiпараметры компилятора GCC / G ++ (я не мог понять вышеприведенное описание)?
  • Может кто-нибудь сказать мне правильные обстоятельства для использования этих двух вариантов?
  • Когда я должен их использовать?
  • Они важны?
huahsin68
источник

Ответы:

84

Компиляторы GCC всегда пытаются скомпилировать вашу программу, если это вообще возможно. Однако в некоторых случаях стандарты C и C ++ указывают, что некоторые расширения запрещены. Соответствующие компиляторы, такие как gcc или g ++, должны выдавать диагностику при обнаружении этих расширений. Например, опция -pedantic компилятора gcc заставляет gcc выдавать предупреждения в таких случаях. Использование более строгой -pedantic-errorsопции преобразует такие диагностические предупреждения в ошибки, которые могут привести к сбою компиляции в таких точках. Только те конструкции, отличные от ISO, которые должны быть помечены соответствующим компилятором, будут генерировать предупреждения или ошибки.

Wazery
источник
3
Стандарты ISO C и C ++ только «запрещают расширения» в том смысле, что расширение не должно изменять поведение любой соответствующей программы. Компилятор не обязан отклонять любую программу, которая использует расширения.
ММ
@MM: Важно отметить, что когда некоторые компиляторы принимают полезную конструкцию, а другие отклоняют ее, «компромисс» Комитета должен заключаться в том, что соответствующая реализация должна выпускать диагностику, которую программисты могут затем игнорировать, таким образом избегая необходимости для Комитета либо поручить или запретить конструкцию.
суперкат
105

Я использую это все время в своем коде.

-ansiФлаг эквивалентен -std=c89. Как уже отмечалось, он отключает некоторые расширения GCC. Добавление -pedanticотключает больше расширений и генерирует больше предупреждений. Например, если у вас строковый литерал длиннее 509 символов, то -pedanticпредупреждает об этом, поскольку он превышает минимальный предел, требуемый стандартом C89. То есть каждый компилятор C89 должен принимать строки длиной 509; им разрешено принимать более длинные строки, но если вы педантичны, нельзя использовать более длинные строки, даже если компилятору разрешено принимать более длинные строки, и без предупреждений педантизма GCC их тоже примет.

Джонатан Леффлер
источник
-ansi отключает некоторые расширения GCC, тогда как -pedantic отключает больше расширений. Кажется, что -ansi - это правило первого уровня, а -pedantic - более ограниченное правило. Означает ли это, что с этими двумя вариантами удаления я могу сделать мой код более совместимым с другим компилятором, таким как Microsoft?
huahsin68
4
@ huahsin68: ну, более или менее. MSVC - это довольно отличный от большинства других компилятор, более адаптированный к конкретной экосистеме и недоступный за ее пределами. Он делает много вещей по-своему, что не совпадает со стандартом. Тем не менее, если вы остаетесь со стандартными заголовками и так далее, то MSVC и GCC довольно похожи. Однако использование -std=c89 -pedanticозначает, что вы можете легче перемещаться между различными компиляторами на других платформах. Как только вы начинаете использовать <windows.h>, совместимость с другими системами становится проблематичной.
Джонатан Леффлер
2
@slf: Потому что, как и любой другой поставщик (хотя GNU не продает свой компилятор за наличные), они хотели бы, чтобы вы использовали их проприетарные функции? Или, в более общем плане, потому что они считают расширения полезными и считают, что они должны быть включены по умолчанию.
Джонатан Леффлер
1
По какой - то стоит, и JFTR , я в основном перестали использовать -pedantic, но большая часть моего кода все еще компилирует ОК , когда я снова включить его (одна программа , которая не была явно с помощью __int128типов, которые являются педантично неправильно). Я думаю, что была промежуточная стадия, когда GCC был слишком шумным (на мой взгляд) -pedantic. Я только что протестировал около 300 исходных файлов - некоторый библиотечный код, некоторые команды, некоторые тестовые программы SO - и была только одна ожидаемая проблема. В настоящее время используется GCC 4.8.2 в Mac OS X 10.9.2.
Джонатан Леффлер
1
@JonathanLeffler, да, я спрашиваю, как называется на практике настоящий компилятор, где это не сработает? Есть ли хоть один такой компилятор?
Пейсер
23

-ansiявляется устаревшим переключателем, который запрашивает компилятор в соответствии с 30-летней устаревшей версией стандарта C , ISO / IEC 9899: 1990 , который по сути является ребрендингом стандарта ANSI X3.159-1989 «Язык программирования C» . Почему устарел? Потому что после того, как C90 был опубликован ISO, ISO отвечал за стандартизацию C, и любые технические исправления к C90 были опубликованы ISO. Таким образом, он более пригоден для использования -std=c90.

Без этого переключателя последние компиляторы C GCC будут соответствовать языку C, стандартизированному в ISO / IEC 9899: 2011 , или новейшей редакции 2018 года.

К сожалению, есть некоторые ленивые поставщики компиляторов, которые считают, что приемлемо придерживаться устаревшей устаревшей стандартной версии, для которой документ по стандартизации даже не доступен из стандартных органов.

Использование переключателя помогает обеспечить компиляцию кода в этих устаревших компиляторах.


Это -pedanticинтересный. В отсутствие -pedantic, даже когда запрашивается конкретный стандарт, GCC по-прежнему допускает некоторые расширения, которые не приемлемы в стандарте C. Рассмотрим для примера программу

struct test {
    int zero_size_array[0];
};

В пункте 6.7.6.2p1 проекта С11 n1570 говорится :

В дополнение к необязательным квалификаторам типов и ключевому слову static, [и] могут разделять выражение или *. Если они разграничивают выражение (которое определяет размер массива), выражение должно иметь целочисленный тип. Если выражение является константным выражением, оно должно иметь значение больше нуля. [...]

Стандарт C требует, чтобы длина массива была больше нуля; и этот пункт в ограничениях ; Стандарт гласит следующее 5.1.1.3p1 :

Соответствующая реализация должна генерировать по крайней мере одно диагностическое сообщение (идентифицированное определенным реализацией способом), если блок преобразования или блок предварительной обработки содержит нарушение какого-либо синтаксического правила или ограничения, даже если поведение также явно указано как неопределенное или реализация-реализация. определены. Диагностические сообщения не должны создаваться при других обстоятельствах. 9)

Однако, если вы скомпилируете программу gcc -c -std=c90 pedantic_test.c, предупреждение не выдается.

-pedanticзаставляет компилятор фактически соответствовать стандарту C ; поэтому теперь он выдаст диагностическое сообщение, как того требует стандарт:

gcc -c -pedantic -std=c90 pedantic_test.c
pedantic_test.c:2:9: warning: ISO C forbids zero-size array zero_size_array [-Wpedantic]
     int zero_size_array[0];
         ^~~~~~~~~~~~~~~

Таким образом, для максимальной переносимости указание версии стандарта недостаточно, вы также должны использовать -pedantic(или -pedantic-errors), чтобы убедиться, что GCC действительно соответствует букве стандарта.


Последняя часть вопроса была об использовании -ansiс C ++ . ANSI никогда не стандартизировал язык C ++ - только перенял его из ISO, так что это примерно так же важно, как сказать «английский язык стандартизирован Францией». Однако GCC все еще, кажется, принимает это для C ++, как бы глупо это ни звучало.

Антти Хаапала
источник
4
Обратите внимание, что были внесены дополнительные изменения в стандарт языка. Сегодня я обычно скомпилирую -std=c11 -Wall -Wextra -Wpedantic -Wconversion.
Дэвислор
14

По сути, это сделает ваш код намного проще для компиляции под другими компиляторами, которые также реализуют стандарт ANSI, и, если вы осторожны, в каких библиотеках / вызовах API вы используете, под другими операционными системами / платформами.

Первый, отключает ОСОБЫЕ функции GCC. (-ansi) Второй, будет жаловаться на НИЧЕГО вообще на то, что не соответствует стандарту (не только специфические особенности GCC, но и ваши конструкции тоже.) (-pedantic).

Франсиско Сото
источник
6

Если ваш код должен быть переносимым, вы можете проверить, что он компилируется без каких-либо расширений gcc или других нестандартных функций. Если ваш код компилируется -pedantic -ansiтогда, теоретически он должен компилироваться нормально с любым другим стандартным компилятором ANSI.

Пол Р
источник
4
-pedanticне отключает все расширения, это оставляет кучу вещей с двойным подчеркиванием. Поэтому было бы точнее сказать, что если ваш код компилируется -pedantic -ansi, и он также выглядит правдоподобно, как если бы он компилировался в других реализациях, то он будет компилироваться.
Стив Джессоп
3
Вы упоминаете двойное подчеркивание, это звучит интересно. На что именно вы ссылаетесь?
huahsin68
Одним из примеров является встроенный код ассемблера gcc "__asm ​​__ ()", который подходит для gcc, но эта вещь с двойным подчеркиванием может не сработать, скажем, на компиляторе Windows, даже если этот компилятор действительно соответствовал стандарту.
3

Если вы пишете код, который вы планируете собирать, который будет компилироваться на самых разных платформах, с несколькими различными компиляторами, то использование этих флагов самостоятельно поможет вам не создавать код, который компилируется только в GCC.

Damien_The_Unbeliever
источник
2
под некоторыми версиями GCC!
Мохамед Амджад ЛАСРИ
1

Другие ответили достаточно. Я просто хотел бы добавить несколько примеров частых расширений:

mainФункция возвращения void. Это не определено стандартом, то есть оно будет работать только на некоторых компиляторах (включая GCC), но не на других. Кстати, int main()и int main(int, char**)две подписи, которые стандарт определяет.

Другое популярное расширение - возможность объявлять и определять функции внутри других функций:

void f()
{
    void g()
    {
       // ...
    }

    // ...
    g();
    // ...
}

Это нестандартно. Если вы хотите такое поведение, посмотрите лямбды C ++ 11

Энн Майкл
источник
0

Pedantic делает так, что компилятор gcc отклоняет все расширения GNU C, а не только те, которые делают его совместимым с ANSI.

Мартин Конечни
источник
1
Это так интересно. Вы упоминаете расширение GNU C, и это расширение может и не может быть в стандарте ANSI. Могу ли я иметь больше информации относительно этого. Где я могу получить эти соответствующие ресурсы?
huahsin68