Яка мета використання -pedantic у компіляторі GCC / G ++?


136

Ця примітка говорить:

-ansi: повідомляє компілятору реалізувати параметр мови ANSI. Це вимикає певні "особливості" GCC, несумісні зі стандартом ANSI.

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

Насамперед:

  • Яка мета -pedanticі -ansiпараметри компілятора GCC / G ++ (я не міг зрозуміти вищеописаний опис)?
  • Чи може хтось сказати мені правильні обставини використання цих двох варіантів?
  • Коли я повинен їх використовувати?
  • Вони важливі?

Відповіді:


84

Компілятори GCC завжди намагаються скласти вашу програму, якщо це взагалі можливо. Однак у деяких випадках стандарти C та C ++ вказують, що певні розширення заборонені. Відповідні компілятори, такі як gcc або g ++, повинні видавати діагностику, коли виникають ці розширення. Наприклад, специфічна опція компілятора gcc викликає попередження попередження gcc у таких випадках. Використання більш суворої -pedantic-errorsопції перетворює такі діагностичні попередження в помилки, які спричинить збій збірки в таких точках. Лише ті конструкції, які не належать ISO, для яких потрібно позначити відповідний компілятор, генерують попередження або помилки.


3
Стандарти ISO C і C ++ "забороняють розширення", оскільки розширення не повинно змінювати поведінку будь-якої програми, що відповідає програмі. Компілятор не змушений відхиляти будь-яку програму, яка використовує розширення.
ММ

@MM: Важливо зауважити, що коли деякі компілятори приймуть корисну конструкцію, а інші відкидають її, "компроміс" Комітету полягав у тому, щоб відповідна реалізація повинна випустити діагностику, яку програмісти можуть потім ігнорувати, таким чином уникаючи необхідності в Комітеті або мандат, або забороняти конструкцію.
supercat

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, Так, я запитую, як називається фактичний компілятор на практиці, де це не працює? Чи є навіть один такий компілятор?
Pacerier

23

-ansi- це застарілий комутатор, який вимагає від компілятора скласти відповідно до 30-річної застарілої редакції стандарту C , ISO / IEC 9899: 1990 , що по суті є ребрендингом стандарту ANSI X3.159-1989 "Мова програмування C" . Чому застарілий? Оскільки після опублікування C90 ISO був ISO, відповідав за стандартизацію С., а будь-які технічні виправлення до C90 були опубліковані ISO, тому більш доцільним є використання -std=c90.

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

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

Використання комутатора допомагає забезпечити компіляцію коду в цих застарілих компіляторах.


-pedanticЄ цікавим. За відсутності -pedantic, навіть коли вимагається конкретний стандарт, GCC все одно дозволить розширити деякі розширення, неприйнятні для стандарту C. Розглянемо для прикладу програму

struct test {
    int zero_size_array[0];
};

C11 проект n1570 пункту 6.7.6.2p1 каже :

Окрім необов'язкових класифікаторів типу та ключового слова статичний, [і] може розмежувати вираз або *. Якщо вони розмежовують вираз (який визначає розмір масиву), вираз має цілий тип. Якщо вираз є постійним виразом, він повинен мати значення, що перевищує нуль. [...]

Стандарт 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, але і ваші конструкції.) (-педантично).


6

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


4
-pedanticне вимикає всіх розширень, це залишає на купі подвійних підкреслень. Тому може бути більш точним сказати, що якщо ваш код компілюється з -pedantic -ansi, і він також виглядає правдоподібно, як він може компілюватися в інших реалізаціях, то він буде компілюватися.
Стів Джессоп

3
Ви згадуєте речі з подвійним підкресленням, це звучить цікаво. Що саме ти хочеш?
huahsin68

Одним із прикладів є вбудований код складання gcc "__asm ​​__ ()", який добре підходить для gcc, але ця подвійна річ підкреслення може не працювати, скажімо, компілятором Windows, навіть якщо цей компілятор відповідав стандарту.

3

Якщо ви пишете код, який, на вашу думку, збиратиметься на різних платформах, з кількома різними компіляторами, то використання самих цих прапорів допоможе вам не створювати код, який компілюється лише під GCC.


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