Jaki jest cel używania -pedantic w kompilatorze GCC / G ++?

136

Ta notatka mówi:

-ansi: informuje kompilator, aby zaimplementował opcję języka ANSI. Powoduje to wyłączenie pewnych „funkcji” GCC, które są niezgodne ze standardem ANSI.

-pedantic: używane w połączeniu z -ansi, mówi kompilatorowi, aby ściśle przestrzegał standardu ANSI, odrzucając każdy kod, który nie jest zgodny.

Po pierwsze:

  • Jaki jest cel -pedantici -ansiopcje kompilatora GCC / G ++ (nie mogłem zrozumieć powyższego opisu)?
  • Czy ktoś może mi powiedzieć, w jakich okolicznościach należy użyć tych dwóch opcji?
  • Kiedy powinienem ich używać?
  • Czy są ważne?
huahsin68
źródło

Odpowiedzi:

84

Kompilatory GCC zawsze próbują skompilować twój program, jeśli jest to w ogóle możliwe. Jednak w niektórych przypadkach standardy C i C ++ określają, że niektóre rozszerzenia są zabronione. Kompilatory zgodne, takie jak gcc lub g ++, muszą generować diagnostykę, gdy te rozszerzenia zostaną napotkane. Na przykład opcja -pedantyczna kompilatora gcc powoduje, że gcc generuje ostrzeżenia w takich przypadkach. Użycie -pedantic-errorsopcji bardziej rygorystycznej przekształca takie ostrzeżenia diagnostyczne w błędy, które spowodują niepowodzenie kompilacji w takich punktach. Tylko te konstrukcje inne niż ISO, które muszą być oznaczone przez zgodny kompilator, będą generować ostrzeżenia lub błędy.

Wazery
źródło
3
Standardy ISO C i C ++ „zabraniają rozszerzeń” tylko w tym sensie, że rozszerzenie nie może zmieniać zachowania żadnego zgodnego programu. Kompilator nie jest zmuszony do odrzucenia żadnego programu, który używa rozszerzeń.
MM
@MM: Ważne jest, aby pamiętać, że gdy niektórzy kompilatorzy zaakceptowaliby użyteczną konstrukcję, a inni ją odrzucili, „kompromisem” Komitetu było wydanie zgodnej implementacji, która musi wydać diagnostykę, którą programiści mogliby następnie zignorować, unikając w ten sposób potrzeby komitetu albo nakazać, albo zabronić konstrukcji.
supercat
105

Używam go cały czas w moim kodowaniu.

-ansiFlaga jest równoważna -std=c89. Jak wspomniano, wyłącza niektóre rozszerzenia GCC. Dodanie -pedanticwyłącza więcej rozszerzeń i generuje więcej ostrzeżeń. Na przykład, jeśli masz literał ciągu dłuższy niż 509 znaków, -pedanticostrzega o tym, ponieważ przekracza minimalny limit wymagany przez standard C89. Oznacza to, że każdy kompilator C89 musi akceptować łańcuchy o długości 509; mogą akceptować dłużej, ale jeśli jesteś pedantyczny, używanie dłuższych ciągów nie jest przenośne, nawet jeśli kompilator może akceptować dłuższe ciągi i bez pedantycznych ostrzeżeń, GCC też je zaakceptuje.

Jonathan Leffler
źródło
-ansi wyłącza niektóre rozszerzenia GCC, podczas gdy -pedantic wyłącza więcej rozszerzeń. Wygląda na to, że -ansi jest regułą pierwszego poziomu niż -pedantyczna jest regułą bardziej ograniczoną. Czy to oznacza, że ​​po usunięciu tych dwóch opcji mój kod może być bardziej zgodny z innym kompilatorem, takim jak Microsoft?
huahsin68
4
@ huahsin68: cóż, mniej więcej. MSVC jest kompilatorem raczej innym niż większość innych, bardziej dostosowanym do konkretnego ekosystemu i niedostępnym poza nim. Wiele rzeczy robi po swojemu - co nie jest tym samym, co standard. Niemniej jednak, jeśli pozostaniesz przy standardowych nagłówkach i tak dalej, MSVC i GCC są dość podobne. Jednak używanie -std=c89 -pedanticoznacza, że ​​możesz łatwiej poruszać się między różnymi kompilatorami na innych platformach. Jak tylko zaczniesz używać <windows.h>, kompatybilność z innymi systemami staje się problematyczna.
Jonathan Leffler
2
@slf: Ponieważ, jak każdy inny dostawca (chociaż GNU nie sprzedaje swojego kompilatora za gotówkę), chcieliby, abyś używał ich zastrzeżonych funkcji? Lub, bardziej ogólnie, ponieważ uważają rozszerzenia za przydatne i uważają, że powinny być domyślnie włączone.
Jonathan Leffler
1
Bez względu na to, co jest warte, i JFTR , przeważnie przestałem używać -pedantic, ale większość mojego kodu nadal kompiluje się dobrze po ponownym włączeniu (jeden program, który tego nie robił, jawnie używał __int128typów, które pedantycznie niepoprawne). Myślę, że był etap pośredni, kiedy GCC było zbyt głośne (jak na mój gust) -pedantic. Właśnie przetestowałem około 300 plików źródłowych - trochę kodu biblioteki, kilka poleceń, kilka programów testowych SO - i był tylko jeden, którego można się było spodziewać. Obecnie używasz GCC 4.8.2 w systemie Mac OS X 10.9.2.
Jonathan Leffler
1
@JonathanLeffler, Tak, pytam, jaka jest nazwa rzeczywistego kompilatora w praktyce, gdzie to nie zadziała? Czy jest chociaż jeden taki kompilator?
Pacerier
23

-ansijest przestarzały przełącznik, który żąda kompilator skompilować zgodnie z 30-letnim przestarzałego rewizji standardu C , ISO / IEC 9899: 1990 , który jest zasadniczo rebranding z ANSI X3.159-1989 „Język programowania C . Dlaczego przestarzałe? Ponieważ po opublikowaniu C90 przez ISO, ISO było odpowiedzialne za standaryzację C, a wszelkie poprawki techniczne do C90 zostały opublikowane przez ISO -std=c90.

Bez tego przełącznika najnowsze kompilatory GCC C będą zgodne z językiem C znormalizowanym w ISO / IEC 9899: 2011 lub najnowszej wersji 2018.

Niestety, są niektórzy leniwi dostawcy kompilatorów, którzy uważają, że dopuszczalne jest trzymanie się starszej, przestarzałej wersji standardu, dla której dokument normalizacyjny nie jest nawet dostępny w jednostkach standardowych.

Korzystanie z przełącznika pomaga zapewnić, że kod powinien zostać skompilowany w tych przestarzałych kompilatorach.


To -pedanticjest interesujące. W przypadku braku -pedantic, nawet jeśli zażądano określonego standardu, GCC nadal będzie zezwalać na niektóre rozszerzenia, które nie są akceptowane w standardzie C. Weźmy na przykład program

struct test {
    int zero_size_array[0];
};

Projekt C11 n1570, paragraf 6.7.6.2p1 mówi :

Oprócz opcjonalnych kwalifikatorów typu i słowa kluczowego static, [i] może ograniczać wyrażenie lub *. Jeśli ograniczają wyrażenie (które określa rozmiar tablicy), wyrażenie powinno mieć typ całkowity. Jeżeli wyrażenie jest wyrażeniem stałym, powinno mieć wartość większą od zera. […]

Standard C wymaga, aby długość tablicy była większa niż zero; a ten ustęp jest w ograniczeniach ; norma mówi, co następuje 5.1.1.3p1 :

Zgodna implementacja powinna wygenerować co najmniej jeden komunikat diagnostyczny (zidentyfikowany w sposób zdefiniowany w implementacji), jeśli jednostka translacyjna lub jednostka translacyjna przetwarzająca wstępnie zawiera naruszenie jakiejkolwiek reguły składniowej lub ograniczenia, nawet jeśli zachowanie jest również wyraźnie określone jako nieokreślone lub implementacja zdefiniowane. W innych okolicznościach komunikaty diagnostyczne nie muszą być generowane.

Jeśli jednak skompilujesz program z gcc -c -std=c90 pedantic_test.c, nie zostanie wyświetlone żadne ostrzeżenie.

-pedanticpowoduje, że kompilator faktycznie jest zgodny ze standardem C ; więc teraz wyświetli komunikat diagnostyczny, zgodnie z wymaganiami normy:

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];
         ^~~~~~~~~~~~~~~

Tak więc, aby zapewnić maksymalną przenośność, określenie wersji standardu nie wystarczy, należy również użyć -pedantic(lub -pedantic-errors), aby upewnić się, że GCC rzeczywiście jest zgodne z literą normy.


Ostatnia część pytania dotyczyła używania -ansiz C ++ . ANSI nigdy nie znormalizowało języka C ++ - tylko przejęło go z ISO, więc ma to tyle samo sensu, co powiedzenie „angielski zgodnie z normą we Francji”. Jednak GCC nadal wydaje się akceptować to dla C ++, tak głupio jak się wydaje.

Antti Haapala
źródło
4
Należy zauważyć, że wprowadzono dalsze poprawki standardu językowego. Dzisiaj zazwyczaj kompiluję z -std=c11 -Wall -Wextra -Wpedantic -Wconversion.
Davislor,
14

Zasadniczo znacznie ułatwi to kompilację kodu pod innymi kompilatorami, które również implementują standard ANSI, i, jeśli uważasz, w których bibliotekach / wywołaniach API używasz, w innych systemach operacyjnych / platformach.

Pierwsza z nich wyłącza SZCZEGÓLNE funkcje GCC. (-ansi) Drugi będzie narzekał na WSZYSTKO, co nie jest zgodne ze standardem (nie tylko specyficzne cechy GCC, ale także twoje konstrukcje). (-pedantyczny).

Francisco Soto
źródło
6

Jeśli Twój kod musi być przenośny , możesz sprawdzić, czy kompiluje się bez żadnych rozszerzeń gcc lub innych niestandardowych funkcji. Jeśli twój kod kompiluje się z, -pedantic -ansito teoretycznie powinien skompilować się dobrze z każdym innym standardowym kompilatorem ANSI.

Paul R.
źródło
4
-pedanticnie wyłącza wszystkich rozszerzeń, pozostawia kilka elementów z podwójnym podkreśleniem. Dlatego dokładniejsze może być stwierdzenie, że jeśli twój kod kompiluje się z programem -pedantic -ansi, a także wygląda na to, że może się skompilować w innych implementacjach, to się skompiluje.
Steve Jessop
3
Wspominasz o podwójnych podkreśleniach, to brzmi interesująco. Co dokładnie masz na myśli?
huahsin68
Jednym z przykładów jest wbudowany kod asemblera gcc „__asm ​​__ ()”, który jest odpowiedni dla gcc, ale to podwójne podkreślenie może nie działać na, powiedzmy, kompilatorze Windows, nawet jeśli ten kompilator był zgodny ze standardem.
3

Jeśli piszesz kod, który według Ciebie ma być kompilowany na wielu różnych platformach, z wieloma różnymi kompilatorami, to użycie tych flag pomoże Ci upewnić się, że nie tworzysz kodu, który kompiluje się tylko pod GCC.

Damien_The_Unbeliever
źródło
2
w niektórych wersjach GCC!
Mohamed Amjad LASRI,
1

Inni odpowiedzieli dostatecznie. Chciałbym tylko dodać kilka przykładów częstych rozszerzeń:

mainFunkcja powrocie void. Nie jest to zdefiniowane w standardzie, co oznacza, że ​​będzie działać tylko na niektórych kompilatorach (w tym GCC), ale nie na innych. By the way, int main()i int main(int, char**)są dwa podpisy, że standard nie definiuje.

Innym popularnym rozszerzeniem jest możliwość deklarowania i definiowania funkcji wewnątrz innych funkcji:

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

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

To jest niestandardowe. Jeśli chcesz tego rodzaju zachowania, sprawdź lambdy języka C ++ 11

Enn Michael
źródło
0

Pedantic sprawia, że ​​kompilator gcc odrzuca wszystkie rozszerzenia GNU C, a nie tylko te, które czynią go kompatybilnym z ANSI.

Martin Konecny
źródło
1
To jest takie interesujące. Wspominasz o rozszerzeniu GNU C, które może, ale nie musi, być zgodne ze standardem ANSI. Czy mogę uzyskać więcej informacji na ten temat. Gdzie mogę uzyskać te odpowiednie zasoby?
huahsin68