วัตถุประสงค์ของการใช้ -pedantic ในคอมไพเลอร์ GCC / G ++ คืออะไร?


140

หมายเหตุนี้ระบุว่า:

-ansi: บอกให้คอมไพเลอร์ใช้ตัวเลือกภาษา ANSI สิ่งนี้จะปิด "คุณลักษณะ" บางอย่างของ GCC ซึ่งเข้ากันไม่ได้กับมาตรฐาน ANSI

-pedantic: ใช้ร่วมกับ-ansiสิ่งนี้บอกให้คอมไพลเลอร์ปฏิบัติตามมาตรฐาน ANSI อย่างเคร่งครัดโดยปฏิเสธรหัสใด ๆ ที่ไม่เป็นไปตามข้อกำหนด

สิ่งแรกแรก:

  • วัตถุประสงค์ของการคืออะไร-pedanticและ-ansiตัวเลือกของคอมไพเลอร์ GCC / G ++ (ผมไม่เข้าใจคำอธิบายข้างต้น)?
  • ใครช่วยบอกฉันถึงสถานการณ์ที่เหมาะสมในการใช้สองตัวเลือกนี้
  • ฉันควรใช้เมื่อใด
  • มีความสำคัญหรือไม่?

คำตอบ:


88

คอมไพเลอร์ GCC พยายามคอมไพล์โปรแกรมของคุณเสมอหากเป็นไปได้ อย่างไรก็ตามในบางกรณีมาตรฐาน C และ C ++ ระบุว่าห้ามใช้ส่วนขยายบางอย่าง คอมไพเลอร์ที่สอดคล้องกันเช่น gcc หรือ g ++ ต้องทำการวินิจฉัยเมื่อพบส่วนขยายเหล่านี้ ตัวอย่างเช่นอ็อพชัน -pedantic ของคอมไพเลอร์ gcc ทำให้ gcc ออกคำเตือนในกรณีดังกล่าว การใช้-pedantic-errorsตัวเลือกที่เข้มงวดขึ้น จะแปลงคำเตือนการวินิจฉัยดังกล่าวเป็นข้อผิดพลาดที่จะทำให้การคอมไพล์ล้มเหลวในจุดดังกล่าว เฉพาะโครงสร้างที่ไม่ใช่ ISO ที่ต้องแฟล็กโดยคอมไพเลอร์ที่สอดคล้องเท่านั้นที่จะสร้างคำเตือนหรือข้อผิดพลาด


3
มาตรฐาน ISO C และ C ++ "ห้ามส่วนขยาย" เท่านั้นโดยที่ส่วนขยายจะต้องไม่เปลี่ยนแปลงลักษณะการทำงานของโปรแกรมที่สอดคล้องกัน คอมไพเลอร์ไม่ได้บังคับให้ปฏิเสธโปรแกรมใด ๆ ที่ใช้ส่วนขยาย
MM

@MM: สิ่งสำคัญคือต้องทราบว่าเมื่อคอมไพเลอร์บางตัวยอมรับโครงสร้างที่เป็นประโยชน์และคนอื่น ๆ จะปฏิเสธ "การประนีประนอม" ของคณะกรรมการคือการดำเนินการให้สอดคล้องต้องออกการวินิจฉัยซึ่งโปรแกรมเมอร์สามารถเพิกเฉยได้ดังนั้นจึงหลีกเลี่ยงความจำเป็นที่คณะกรรมการจะต้อง ไม่ว่าจะมอบอำนาจหรือห้ามการก่อสร้าง
supercat

108

ฉันใช้มันตลอดเวลาในการเขียนโค้ด

ธงเทียบเท่ากับ-ansi -std=c89ตามที่ระบุไว้จะปิดส่วนขยายบางส่วนของ GCC การเพิ่ม-pedanticจะปิดส่วนขยายเพิ่มเติมและสร้างคำเตือนเพิ่มเติม ตัวอย่างเช่นหากคุณมีสตริงลิเทอรัลยาวเกิน 509 อักขระจะ-pedanticเตือนเกี่ยวกับสิ่งนั้นเนื่องจากเกินขีด จำกัด ขั้นต่ำที่กำหนดโดยมาตรฐาน C89 นั่นคือคอมไพเลอร์ C89 ทุกตัวต้องยอมรับสตริงที่มีความยาว 509 พวกเขาได้รับอนุญาตให้ยอมรับอีกต่อไป แต่หากคุณเป็นคนอวดดีก็ไม่สามารถพกพาได้ที่จะใช้สตริงที่ยาวกว่าแม้ว่าคอมไพเลอร์จะได้รับอนุญาตให้ยอมรับสตริงที่ยาวกว่าและหากไม่มีคำเตือนที่อวดดี GCC ก็จะยอมรับด้วยเช่นกัน


-ansi ปิดส่วนขยายบางส่วนของ GCC ในขณะที่ -pedantic ปิดส่วนขยายเพิ่มเติม ดูเหมือนว่า -ansi เป็นกฎระดับแรกแล้ว -pedantic เป็นกฎที่ จำกัด มากกว่า หมายความว่าสองตัวเลือกนี้ลบฉันสามารถทำให้รหัสของฉันเข้ากันได้กับคอมไพเลอร์อื่น ๆ เช่น Microsoft one หรือไม่
huahsin68

4
@ huahsin68: ไม่มากก็น้อย. MSVC เป็นคอมไพเลอร์ที่ค่อนข้างแตกต่างจากคนอื่น ๆ ส่วนใหญ่ปรับให้เข้ากับระบบนิเวศเฉพาะและไม่สามารถใช้งานได้ มันทำหลายสิ่งหลายอย่างในแบบของตัวเองซึ่งไม่เหมือนกับมาตรฐาน อย่างไรก็ตามหากคุณอยู่กับส่วนหัวมาตรฐานไปเรื่อย ๆ MSVC และ GCC ก็ค่อนข้างคล้ายกัน อย่างไรก็ตามการใช้-std=c89 -pedanticหมายความว่าคุณสามารถย้ายระหว่างคอมไพเลอร์ต่างๆบนแพลตฟอร์มอื่น ๆ ได้ง่ายขึ้น ทันทีที่คุณเริ่มใช้<windows.h>ความเข้ากันได้กับระบบอื่น ๆ จะกลายเป็นปัญหา
Jonathan Leffler

2
@slf: เนื่องจากเช่นเดียวกับผู้ขายรายอื่น ๆ (แม้ว่า GNU จะไม่ขายคอมไพเลอร์เป็นเงินสด) พวกเขาต้องการให้คุณใช้คุณสมบัติที่เป็นกรรมสิทธิ์ของพวกเขา? หรือโดยทั่วไปเนื่องจากถือว่าส่วนขยายมีประโยชน์และคิดว่าควรเปิดใช้งานโดยค่าเริ่มต้น
Jonathan Leffler

1
สำหรับสิ่งที่มันมีค่าและJFTRฉันได้หยุดส่วนใหญ่ใช้-pedanticแต่ส่วนมากของรหัสของฉันยังคงรวบรวมตกลงเมื่อฉันเปิดใช้งานได้ (โปรแกรมหนึ่งที่ไม่ได้ถูกใช้อย่างชัดเจน__int128ชนิดซึ่งมีความไม่ถูกต้องอวด) ผมคิดว่าจะมีขั้นตอนการแทรกแซงเมื่อ GCC ก็มีเสียงดังมากเกินไป (สำหรับความชอบของฉัน) -pedanticด้วย ฉันเพิ่งทดสอบซอร์สไฟล์ประมาณ 300 ไฟล์ - รหัสไลบรารีบางคำสั่งบางโปรแกรมทดสอบ SO - และมีเพียงปัญหาที่คาดว่าจะได้รับ ปัจจุบันใช้ GCC 4.8.2 บน Mac OS X 10.9.2
Jonathan Leffler

1
@JonathanLeffler ใช่ฉันกำลังค้นหาชื่อของคอมไพเลอร์ที่แท้จริงในทางปฏิบัติซึ่งจะไม่ทำงานคืออะไร มีคอมไพเลอร์แม้แต่ตัวเดียวหรือไม่?
Pacerier

26

-ansiเป็นสวิทช์ที่ล้าสมัยที่ร้องขอคอมไพเลอร์จะรวบรวมไปตาม 30 ปีการแก้ไขล้าสมัยมาตรฐาน C , มาตรฐาน ISO / IEC 9899: 1990ซึ่งเป็นหลัก rebranding ของมาตรฐาน ANSI X3.159-1989 "การเขียนโปรแกรมภาษา C ทำไมล้าสมัยเพราะหลังจาก C90 เผยแพร่โดย ISO แล้ว ISO ได้รับการดูแลมาตรฐาน C และISO Corrigenda ทางเทคนิคใด ๆถึง 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ไฟล์.
Davislor

14

โดยทั่วไปจะทำให้โค้ดของคุณง่ายขึ้นมากในการคอมไพล์ภายใต้คอมไพเลอร์อื่น ๆ ซึ่งใช้มาตรฐาน ANSI ด้วยและหากคุณระมัดระวังในไลบรารี / api ที่คุณเรียกใช้ภายใต้ระบบปฏิบัติการ / แพลตฟอร์มอื่น ๆ

อันแรกปิดคุณสมบัติเฉพาะของ GCC (-ansi) อันที่สองจะบ่นเกี่ยวกับสิ่งใด ๆ ที่ไม่เป็นไปตามมาตรฐาน (ไม่ใช่เฉพาะคุณลักษณะเฉพาะของ GCC แต่โครงสร้างของคุณด้วย) (-pedantic)


7

หากโค้ดของคุณจำเป็นต้องพกพาคุณสามารถทดสอบได้ว่าคอมไพล์โดยไม่มีส่วนขยาย gcc หรือคุณสมบัติที่ไม่ได้มาตรฐานอื่น ๆ หากโค้ดของคุณรวบรวมตาม-pedantic -ansiทฤษฎีแล้วควรคอมไพล์ตกลงกับคอมไพเลอร์มาตรฐาน ANSI อื่น ๆ


4
-pedanticไม่ได้ปิดส่วนขยายทั้งหมด แต่จะเหลือสิ่งที่ขีดเส้นใต้ไว้มากมาย ดังนั้นจึงอาจถูกต้องมากขึ้นที่จะบอกว่าหากโค้ดของคุณคอมไพล์ด้วย-pedantic -ansiและดูเหมือนว่ามันอาจรวบรวมในการใช้งานอื่น ๆ ด้วยก็จะคอมไพล์
Steve Jessop

3
คุณพูดถึงสิ่งที่ขีดล่างสองครั้งฟังดูน่าสนใจ คุณหมายถึงอะไรกันแน่?
huahsin68

1
ตัวอย่างหนึ่งคือโค้ดแอสเซมบลีแบบอินไลน์ "__asm ​​__ ()" ของ gcc ที่ใช้ได้ดีสำหรับ gcc แต่สิ่งที่ขีดล่างสองครั้งนั้นอาจใช้ไม่ได้กับคอมไพเลอร์ Windows แม้ว่าคอมไพเลอร์นั้นจะเป็นไปตามมาตรฐานก็ตาม

3

หากคุณกำลังเขียนโค้ดที่คุณคิดว่าจะถูกคอมไพล์บนแพลตฟอร์มที่หลากหลายโดยมีคอมไพเลอร์ที่แตกต่างกันจำนวนมากการใช้แฟล็กเหล่านี้ด้วยตัวคุณเองจะช่วยให้แน่ใจว่าคุณไม่ได้สร้างโค้ดที่รวบรวมภายใต้ GCC เท่านั้น


2
ภายใต้ GCC บางเวอร์ชัน!
Mohamed Amjad LASRI

1

คนอื่น ๆ ตอบได้เพียงพอแล้ว ฉันต้องการเพิ่มตัวอย่างของส่วนขยายที่ใช้บ่อย:

ฟังก์ชั่นกลับมาmain voidสิ่งนี้ไม่ได้กำหนดโดยมาตรฐานซึ่งหมายความว่าจะใช้ได้กับคอมไพเลอร์บางตัวเท่านั้น (รวมถึง GCC) แต่จะใช้กับคอมไพเลอร์อื่นไม่ได้ โดยวิธีการint main()และint main(int, char**)เป็นลายเซ็นสองอย่างที่มาตรฐานกำหนด

ส่วนขยายยอดนิยมอีกตัวคือความสามารถในการประกาศและกำหนดฟังก์ชันภายในฟังก์ชันอื่น ๆ :

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

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

สิ่งนี้ไม่เป็นมาตรฐาน หากคุณต้องการพฤติกรรมแบบนี้ลองดูC ++ 11 lambdas


0

Pedantic ทำให้คอมไพเลอร์ gcc ปฏิเสธส่วนขยาย GNU C ทั้งหมดไม่ใช่แค่ส่วนขยายที่ทำให้เข้ากันได้กับ ANSI


1
นี่เป็นความสัมพันธ์กันมาก คุณพูดถึงส่วนขยาย GNU C และส่วนขยายเหล่านั้นอาจและอาจไม่อยู่ในมาตรฐาน ANSI ฉันขอข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ไหม ฉันจะหาแหล่งข้อมูลที่เหมาะสมเหล่านั้นได้ที่ไหน?
huahsin68
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.