Apa tujuan menggunakan -pedantic dalam compiler GCC / G ++?

140

Catatan ini mengatakan:

-ansi: memberi tahu kompilator untuk mengimplementasikan opsi bahasa ANSI. Tindakan ini mematikan "fitur" GCC tertentu yang tidak kompatibel dengan standar ANSI.

-pedantic: digunakan bersama dengan -ansi, ini memberi tahu kompiler untuk mematuhi standar ANSI secara ketat, menolak kode apa pun yang tidak sesuai.

Hal pertama yang pertama:

  • Apa tujuan dari opsi -pedanticdan -ansidari kompiler GCC / G ++ (saya tidak dapat memahami deskripsi di atas)?
  • Adakah yang bisa memberi tahu saya keadaan yang tepat untuk menggunakan kedua opsi ini?
  • Kapan saya harus menggunakannya?
  • Apakah mereka penting?
huahsin68.dll
sumber

Jawaban:

88

Kompiler GCC selalu mencoba mengkompilasi program Anda jika memungkinkan. Namun, dalam beberapa kasus, standar C dan C ++ menetapkan bahwa ekstensi tertentu dilarang. Kompiler yang sesuai seperti gcc atau g ++ harus mengeluarkan diagnostik saat ekstensi ini ditemukan. Misalnya, opsi -pedantic compiler gcc menyebabkan gcc mengeluarkan peringatan dalam kasus seperti itu. Menggunakan -pedantic-errorsopsi yang lebih ketat akan mengubah peringatan diagnostik tersebut menjadi kesalahan yang akan menyebabkan kompilasi gagal pada titik-titik tersebut. Hanya konstruksi non-ISO yang perlu ditandai oleh kompiler yang sesuai yang akan menghasilkan peringatan atau kesalahan.

Wazery
sumber
3
Standar ISO C dan C ++ hanya "melarang ekstensi" di mana ekstensi tidak boleh mengubah perilaku program yang sesuai. Kompilator tidak dipaksa untuk menolak program apa pun yang menggunakan ekstensi.
MM
@ MM: Penting untuk dicatat bahwa ketika beberapa kompiler akan menerima konstruksi yang berguna dan yang lain akan menolaknya, "kompromi" Komite adalah memiliki implementasi yang sesuai harus mengeluarkan diagnostik yang kemudian dapat diabaikan oleh pemrogram, sehingga menghindari kebutuhan Komite untuk baik mengamanatkan atau melarang konstruksi.
supercat
108

Saya menggunakannya sepanjang waktu dalam pengkodean saya.

The -ansibendera setara dengan -std=c89. Seperti yang disebutkan, ini mematikan beberapa ekstensi GCC. Menambahkan akan -pedanticmematikan lebih banyak ekstensi dan menghasilkan lebih banyak peringatan. Misalnya, jika Anda memiliki string literal lebih dari 509 karakter, -pedanticperingatkan tentang itu karena melebihi batas minimum yang disyaratkan oleh standar C89. Artinya, setiap compiler C89 harus menerima string dengan panjang 509; mereka diizinkan untuk menerima lebih lama, tetapi jika Anda bertele-tele, tidak portabel untuk menggunakan string yang lebih panjang, meskipun kompiler diizinkan untuk menerima string yang lebih panjang dan, tanpa peringatan bertele-tele, GCC akan menerimanya juga.

Jonathan Leffler
sumber
-ansi mematikan beberapa ekstensi GCC sedangkan -pedantic mematikan lebih banyak ekstensi. Sepertinya -ansi adalah aturan tingkat pertama, kemudian -pedantik adalah aturan yang lebih terbatas. Apakah ini berarti dengan dua opsi ini hapus saya dapat memiliki kode saya yang lebih kompatibel dengan kompiler lain seperti Microsoft?
huahsin68
4
@ huahsin68: baik, kurang lebih. MSVC adalah kompiler yang agak berbeda dari kebanyakan kompiler lainnya, lebih beradaptasi dengan ekosistem tertentu dan tidak tersedia di luarnya. Ia melakukan banyak hal dengan caranya sendiri - yang tidak sama dengan standar. Namun demikian, jika Anda menggunakan header standar dan seterusnya, maka MSVC dan GCC cukup mirip. Namun, dengan menggunakan -std=c89 -pedanticberarti Anda dapat berpindah dengan lebih mudah di antara kompiler yang berbeda di platform lain. Segera setelah Anda mulai menggunakan <windows.h>, kompatibilitas dengan sistem lain menjadi bermasalah.
Jonathan Leffler
2
@slf: Karena seperti semua vendor lainnya (walaupun GNU tidak menjual kompilernya untuk mendapatkan uang tunai), mereka ingin Anda menggunakan fitur miliknya? Atau, secara lebih umum, karena mereka menganggap ekstensi berguna dan menganggapnya harus diaktifkan secara default.
Jonathan Leffler
1
Untuk apa pun nilainya, dan JFTR , saya sebagian besar telah berhenti menggunakan -pedantic, tetapi sebagian besar kode saya masih mengkompilasi OK ketika saya mengaktifkannya kembali (satu program yang tidak secara eksplisit menggunakan __int128tipe, yang secara pedantically tidak benar). Saya pikir ada tahap intervensi ketika GCC terlalu berisik (untuk saya sukai) -pedantic. Saya baru saja menguji sekitar 300 file sumber - beberapa kode pustaka, beberapa perintah, beberapa program uji SO - dan hanya ada satu masalah yang diharapkan. Saat ini menggunakan GCC 4.8.2 di Mac OS X 10.9.2.
Jonathan Leffler
1
@JonathanLeffler, Ya, saya bertanya-tanya apa nama kompiler aktual dalam praktiknya di mana itu tidak akan berhasil? Apakah ada satu kompiler seperti itu?
Pacerier
26

-ansiadalah sebuah saklar usang yang meminta compiler untuk mengkompilasi sesuai dengan 30 tahun revisi usang dari standar C , ISO / IEC 9899: 1990 , yang pada dasarnya adalah rebranding dari ANSI standar X3.159-1989 "Pemrograman Bahasa C . Mengapa usang? Karena setelah C90 diterbitkan oleh ISO, ISO telah bertanggung jawab atas standardisasi C, dan setiap corrigenda teknis untuk C90 telah diterbitkan oleh ISO. Jadi lebih cenderung menggunakan -std=c90.

Tanpa sakelar ini, compiler GCC C terbaru akan sesuai dengan bahasa C yang distandarisasi dalam ISO / IEC 9899: 2011 , atau revisi terbaru 2018.

Sayangnya ada beberapa vendor compiler malas yang percaya bahwa dapat diterima untuk tetap menggunakan revisi standar lama yang sudah usang, di mana dokumen standardisasi bahkan tidak tersedia dari badan standar.

Menggunakan sakelar membantu memastikan bahwa kode harus dikompilasi di kompiler usang ini.


Ini -pedanticyang menarik. Jika tidak ada -pedantic, meskipun standar tertentu diminta, GCC akan tetap mengizinkan beberapa ekstensi yang tidak dapat diterima dalam standar C. Pertimbangkan misalnya program

struct test {
    int zero_size_array[0];
};

The C11 rancangan n1570 ayat 6.7.6.2p1 mengatakan :

Selain kualifikasi tipe opsional dan kata kunci statis, [dan] dapat membatasi ekspresi atau *. Jika mereka membatasi ekspresi (yang menentukan ukuran array), ekspresi tersebut harus memiliki tipe integer. Jika ekspresi adalah ekspresi konstan, itu harus memiliki nilai lebih besar dari nol. [...]

Standar C mengharuskan panjang array lebih besar dari nol; dan paragraf ini ada dalam batasan ; standar mengatakan 5.1.1.3p1 berikut :

Implementasi yang sesuai harus menghasilkan setidaknya satu pesan diagnostik (diidentifikasi dengan cara yang ditentukan implementasi) jika unit terjemahan praproses atau unit terjemahan berisi pelanggaran aturan atau batasan sintaks, bahkan jika perilaku tersebut juga secara eksplisit ditetapkan sebagai tidak ditentukan atau implementasi- ditentukan. Pesan diagnostik tidak perlu dibuat dalam keadaan lain.9)

Namun, jika Anda mengkompilasi program dengan gcc -c -std=c90 pedantic_test.c, tidak ada peringatan yang dihasilkan.

-pedanticmenyebabkan kompilator benar-benar memenuhi standar C ; jadi sekarang ini akan menghasilkan pesan diagnostik, seperti yang disyaratkan oleh standar:

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

Jadi, untuk portabilitas maksimal, menentukan revisi standar saja tidak cukup, Anda juga harus menggunakan -pedantic(atau -pedantic-errors) untuk memastikan bahwa GCC benar-benar sesuai dengan standar yang berlaku.


Bagian terakhir dari pertanyaan itu adalah tentang penggunaan -ansidengan C ++ . ANSI tidak pernah menstandarkan bahasa C ++ - hanya mengadopsinya dari ISO, jadi ini sama masuk akal dengan mengatakan "Bahasa Inggris seperti yang distandarkan oleh Prancis". Namun GCC tampaknya masih menerimanya untuk C ++, kedengarannya bodoh.

Antti Haapala
sumber
4
Perhatikan bahwa ada revisi lebih lanjut dari standar bahasa. Hari ini saya biasanya mengompilasi dengan -std=c11 -Wall -Wextra -Wpedantic -Wconversion.
Davislor
14

Pada dasarnya, ini akan membuat kode Anda jauh lebih mudah untuk dikompilasi di bawah kompiler lain yang juga menerapkan standar ANSI, dan, jika Anda berhati-hati dengan panggilan libraries / api yang Anda gunakan, di bawah sistem operasi / platform lain.

Yang pertama, mematikan fitur KHUSUS GCC. (-ansi) Yang kedua, akan mengeluh tentang APA SAJA yang tidak sesuai dengan standar (tidak hanya fitur khusus GCC, tetapi juga konstruksi Anda.) (-pedantic).

Francisco Soto
sumber
7

Jika kode Anda harus portabel, Anda dapat menguji apakah kode tersebut dikompilasi tanpa ekstensi gcc atau fitur non-standar lainnya. Jika kode Anda dikompilasi dengan -pedantic -ansimaka dalam teori itu harus mengkompilasi OK dengan kompiler standar ANSI lainnya.

Paul R
sumber
4
-pedantictidak mematikan semua ekstensi, ia meninggalkan banyak hal garis bawah ganda. Jadi, mungkin lebih akurat untuk mengatakan bahwa jika kode Anda dikompilasi -pedantic -ansi, dan juga terlihat masuk akal seperti mungkin dikompilasi pada implementasi lain, maka itu akan dikompilasi.
Steve Jessop
3
Anda menyebutkan hal-hal garis bawah ganda, ini terdengar menarik. Apa sebenarnya yang Anda maksud?
huahsin68
1
Salah satu contohnya adalah kode assembly inline "__asm ​​__ ()" gcc yang baik untuk gcc tetapi hal yang menggarisbawahi ganda itu mungkin tidak berfungsi, katakanlah compiler Windows, bahkan jika compiler itu memenuhi standar.
3

Jika Anda menulis kode yang menurut Anda akan dikompilasi pada berbagai macam platform, dengan sejumlah kompiler yang berbeda, maka menggunakan tanda ini sendiri akan membantu memastikan Anda tidak menghasilkan kode yang hanya dikompilasi di bawah GCC.

Damien_The_Tidak percaya
sumber
2
di bawah beberapa versi GCC!
Mohamed Amjad LASRI
1

Yang lainnya menjawab cukup. Saya hanya ingin menambahkan beberapa contoh ekstensi yang sering:

The mainFungsi kembali void. Ini tidak ditentukan oleh standar, artinya ini hanya akan bekerja pada beberapa kompiler (termasuk GCC), tetapi tidak pada yang lain. Omong-omong, int main()dan int main(int, char**)adalah dua tanda tangan yang didefinisikan oleh standar.

Ekstensi populer lainnya adalah mampu mendeklarasikan dan mendefinisikan fungsi di dalam fungsi lain:

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

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

Ini tidak standar. Jika Anda menginginkan perilaku seperti ini, lihat C ++ 11 lambda

Enn Michael
sumber
0

Pedantic membuatnya sehingga compiler gcc menolak semua ekstensi GNU C tidak hanya yang membuatnya kompatibel dengan ANSI.

Martin Konecny
sumber
1
Ini sangat menarik. Anda menyebutkan ekstensi GNU C, dan ekstensi tersebut mungkin dan mungkin tidak dalam standar ANSI. Bisa saya minta info lebih lanjut tentang ini. Di mana saya bisa mendapatkan sumber daya yang sesuai?
huahsin68