Mục đích của việc sử dụng -pedantic trong trình biên dịch GCC / G ++ là gì?


136

Ghi chú này nói:

-ansi: báo cho trình biên dịch thực hiện tùy chọn ngôn ngữ ANSI. Điều này sẽ tắt một số "tính năng" nhất định của GCC không tương thích với tiêu chuẩn ANSI.

-pedantic: được sử dụng cùng với -ansi, điều này cho biết trình biên dịch tuân thủ nghiêm ngặt tiêu chuẩn ANSI, từ chối bất kỳ mã nào không tuân thủ.

Điều đầu tiên trước tiên:

  • Mục đích của các tùy chọn -pedantic-ansitrình biên dịch GCC / G ++ là gì (tôi không thể hiểu mô tả ở trên)?
  • Bất cứ ai có thể cho tôi biết các trường hợp phù hợp để sử dụng hai tùy chọn này?
  • Khi nào tôi nên sử dụng chúng?
  • Họ có quan trọng không?

Câu trả lời:


84

Trình biên dịch GCC luôn cố gắng biên dịch chương trình của bạn nếu điều này hoàn toàn có thể. Tuy nhiên, trong một số trường hợp, các tiêu chuẩn C và C ++ chỉ định rằng các phần mở rộng nhất định bị cấm. Các trình biên dịch phù hợp như gcc hoặc g ++ phải đưa ra chẩn đoán khi gặp các phần mở rộng này. Ví dụ: tùy chọn -pedantic của trình biên dịch gcc khiến gcc đưa ra cảnh báo trong các trường hợp như vậy. Sử dụng -pedantic-errorstùy chọn chặt chẽ hơn sẽ chuyển đổi các cảnh báo chẩn đoán đó thành các lỗi sẽ khiến quá trình biên dịch bị lỗi tại các điểm đó. Chỉ những cấu trúc không phải ISO được yêu cầu gắn cờ bởi trình biên dịch tuân thủ mới tạo ra các cảnh báo hoặc lỗi.


3
Các tiêu chuẩn ISO C và C ++ chỉ "cấm các phần mở rộng" ở chỗ phần mở rộng không được thay đổi hành vi của bất kỳ chương trình tuân thủ nào. Trình biên dịch không bị buộc phải từ chối bất kỳ chương trình sử dụng phần mở rộng.
MM

@MM: Điều quan trọng cần lưu ý là khi một số trình biên dịch chấp nhận một cấu trúc hữu ích và các trình biên dịch khác sẽ từ chối nó, "thỏa hiệp" của Ủy ban là phải thực hiện tuân thủ phải đưa ra chẩn đoán mà lập trình viên có thể bỏ qua, do đó tránh được Ủy ban phải hoặc ủy thác hoặc cấm xây dựng.
supercat

105

Tôi sử dụng tất cả thời gian trong mã hóa của tôi.

Các -ansilá cờ tương đương với -std=c89. Như đã lưu ý, nó tắt một số phần mở rộng của GCC. Thêm -pedantictắt nhiều tiện ích mở rộng và tạo thêm cảnh báo. Ví dụ: nếu bạn có một chuỗi ký tự dài hơn 509 ký tự, thì -pedanticcảnh báo về điều đó bởi vì nó vượt quá giới hạn tối thiểu theo yêu cầu của tiêu chuẩn C89. Nghĩa là, mọi trình biên dịch C89 phải chấp nhận các chuỗi có độ dài 509; chúng được phép chấp nhận lâu hơn, nhưng nếu bạn là người phạm tội, thì không thể sử dụng chuỗi dài hơn, mặc dù trình biên dịch được phép chấp nhận chuỗi dài hơn và, không có cảnh báo phạm vi, GCC cũng sẽ chấp nhận chúng.


-ansi tắt một số tiện ích mở rộng của GCC trong khi -pedantic tắt nhiều tiện ích mở rộng hơn. Có vẻ như -ansi là quy tắc cấp đầu tiên sau đó -pedantic là quy tắc hạn chế hơn. Có nghĩa là với hai tùy chọn loại bỏ này, tôi có thể có mã của mình tương thích hơn với trình biên dịch khác như Microsoft không?
huahsin68

4
@ huahsin68: tốt, nhiều hay ít. MSVC là một trình biên dịch khá khác biệt so với hầu hết các phần mềm khác, thích nghi hơn với hệ sinh thái cụ thể của nó và không có sẵn bên ngoài nó. Nó thực hiện rất nhiều thứ theo cách riêng của nó - không giống với tiêu chuẩn. Tuy nhiên, nếu bạn ở lại với các tiêu đề tiêu chuẩn, thì MSVC và GCC tương đối giống nhau. Tuy nhiên, sử dụng -std=c89 -pedantickhông có nghĩa là bạn có thể di chuyển dễ dàng hơn giữa các trình biên dịch khác nhau trên các nền tảng khác. Ngay khi bạn bắt đầu sử dụng <windows.h>, khả năng tương thích với các hệ thống khác sẽ trở thành vấn đề.
Jonathan Leffler

2
@slf: Bởi vì giống như mọi nhà cung cấp khác (mặc dù GNU không bán trình biên dịch của họ để lấy tiền mặt), họ có muốn bạn sử dụng các tính năng độc quyền của họ không? Hoặc, nói chung hơn, vì họ coi các tiện ích mở rộng hữu ích và nghĩ rằng chúng nên được bật theo mặc định.
Jonathan Leffler

1
Đối với bất cứ điều gì nó là giá trị, và JFTR , tôi đã hầu như đã ngừng sử dụng -pedantic, nhưng hầu hết các mã của tôi vẫn biên dịch OK khi tôi kích hoạt lại nó (một trong những chương trình đó không được sử dụng một cách rõ ràng __int128các loại, mà vẻ thông thái không chính xác). Tôi nghĩ đã có một giai đoạn can thiệp khi GCC quá ồn ào (theo ý thích của tôi) với -pedantic. Tôi vừa kiểm tra khoảng 300 tệp nguồn - một số mã thư viện, một số lệnh, một số chương trình kiểm tra SO - và chỉ có một vấn đề được mong đợi. Hiện đang sử dụng GCC 4.8.2 trên Mac OS X 10.9.2.
Jonathan Leffler

1
@JonathanLeffler, Vâng, tôi đang truy vấn tên của một trình biên dịch thực tế trong thực tế, nơi nó sẽ không hoạt động? Có một trình biên dịch như vậy không?
Pacerier

23

-ansilà một công tắc lỗi thời mà yêu cầu trình biên dịch để biên dịch theo 30 tuổi phiên bản lỗi thời của chuẩn C , ISO / IEC 9899: 1990 , trong đó chủ yếu là một thương hiệu riêng của các chuẩn ANSI X3.159-1989 "Lập trình ngôn ngữ C . Bởi vì sau khi C90 được xuất bản bởi ISO, ISO đã chịu trách nhiệm về tiêu chuẩn hóa C và bất kỳ chương trình chỉnh sửa kỹ thuật nào đối với C90 đã được ISO xuất bản -std=c90.

Nếu không có công tắc này, các trình biên dịch GCC C gần đây sẽ tuân thủ ngôn ngữ C được tiêu chuẩn hóa trong ISO / IEC 9899: 2011 hoặc phiên bản 2018 mới nhất.

Thật không may, có một số nhà cung cấp trình biên dịch lười biếng tin rằng có thể chấp nhận việc tuân theo bản sửa đổi tiêu chuẩn cũ hơn, mà tài liệu tiêu chuẩn hóa thậm chí không có sẵn từ các cơ quan tiêu chuẩn.

Sử dụng công tắc giúp đảm bảo rằng mã sẽ được biên dịch trong các trình biên dịch lỗi thời này.


Đây -pedanticlà một trong những thú vị. Trong trường hợp không có -pedantic, ngay cả khi một tiêu chuẩn cụ thể được yêu cầu, GCC vẫn sẽ cho phép một số tiện ích mở rộng không được chấp nhận trong tiêu chuẩn C. Xem xét ví dụ chương trình

struct test {
    int zero_size_array[0];
};

Các C11 dự thảo n1570 đoạn 6.7.6.2p1 nói :

Ngoài các loại vòng loại tùy chọn và từ khóa tĩnh, [và] có thể phân định một biểu thức hoặc *. Nếu họ phân định một biểu thức (xác định kích thước của một mảng), biểu thức sẽ có một kiểu số nguyên. Nếu biểu thức là một biểu thức không đổi, nó sẽ có giá trị lớn hơn 0. [...]

Tiêu chuẩn C yêu cầu độ dài mảng lớn hơn 0; và đoạn này là trong các ràng buộc ; tiêu chuẩn cho biết 5.1.1.3p1 sau đây :

Việc triển khai tuân thủ sẽ tạo ra ít nhất một thông báo chẩn đoán (được xác định theo cách xác định thực hiện) nếu đơn vị dịch hoặc đơn vị dịch tiền xử lý có vi phạm bất kỳ quy tắc cú pháp hoặc ràng buộc nào, ngay cả khi hành vi cũng được xác định rõ ràng là không xác định hoặc thực hiện- xác định. Thông điệp chẩn đoán không cần phải được tạo ra trong các trường hợp khác.9)

Tuy nhiên, nếu bạn biên dịch chương trình với gcc -c -std=c90 pedantic_test.c, không có cảnh báo nào được tạo ra.

-pedanticlàm cho trình biên dịch thực sự tuân thủ tiêu chuẩn C ; vì vậy bây giờ nó sẽ tạo ra một thông báo chẩn đoán, theo yêu cầu của tiêu chuẩn:

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

Do đó, đối với tính di động tối đa, việc chỉ định sửa đổi tiêu chuẩn là không đủ, bạn cũng phải sử dụng -pedantic(hoặc -pedantic-errors) để đảm bảo rằng GCC thực sự tuân thủ thư của tiêu chuẩn.


Phần cuối của câu hỏi là về việc sử dụng -ansivới C ++ . ANSI không bao giờ tiêu chuẩn hóa ngôn ngữ C ++ - chỉ áp dụng ngôn ngữ này từ ISO, vì vậy điều này có ý nghĩa nhiều như nói "Tiếng Anh theo tiêu chuẩn của Pháp". Tuy nhiên, GCC dường như vẫn chấp nhận nó cho C ++, ngu ngốc như nó nghe.


4
Lưu ý rằng đã có sửa đổi thêm về tiêu chuẩn ngôn ngữ. Hôm nay tôi thường biên dịch với -std=c11 -Wall -Wextra -Wpedantic -Wconversion.
Davislor

14

Về cơ bản, nó sẽ làm cho mã của bạn dễ dàng biên dịch hơn trong các trình biên dịch khác cũng thực hiện tiêu chuẩn ANSI và, nếu bạn cẩn thận trong việc các thư viện / api gọi bạn sử dụng, trong các hệ điều hành / nền tảng khác.

Cái đầu tiên, tắt các tính năng CỤ THỂ của GCC. (-ansi) Cái thứ hai, sẽ phàn nàn về BẤT CỨ điều gì không tuân thủ tiêu chuẩn (không chỉ các tính năng cụ thể của GCC, mà cả các cấu trúc của bạn nữa.) (-pedantic).


6

Nếu mã của bạn cần phải di động thì bạn có thể kiểm tra xem nó có biên dịch mà không có bất kỳ tiện ích mở rộng gcc hoặc các tính năng không chuẩn nào khác không. Nếu -pedantic -ansitheo lý thuyết, mã của bạn sẽ biên dịch với OK, với bất kỳ trình biên dịch chuẩn ANSI nào khác.


4
-pedantickhông tắt tất cả các tiện ích mở rộng, nó để lại một loạt các công cụ gạch dưới hai lần. Vì vậy, có thể chính xác hơn để nói rằng nếu mã của bạn biên dịch với -pedantic -ansi, và nó cũng có vẻ hợp lý giống như nó có thể biên dịch trên các triển khai khác, thì nó sẽ biên dịch.
Steve Jessop

3
Bạn đề cập đến công cụ hai dấu gạch dưới, điều này nghe có vẻ thú vị. Chính xác thì bạn đang đề cập đến cái gì?
huahsin68

Một ví dụ là mã lắp ráp nội tuyến "__asm ​​__ ()" của gcc phù hợp với gcc nhưng điều đó gạch dưới hai lần có thể không hoạt động trên trình biên dịch Windows, ngay cả khi trình biên dịch đó đã tuân thủ tiêu chuẩn.

3

Nếu bạn đang viết mã mà bạn dự tính sẽ được biên dịch trên nhiều nền tảng khác nhau, với một số trình biên dịch khác nhau, thì việc sử dụng các cờ này sẽ giúp đảm bảo bạn không tạo mã chỉ biên dịch theo GCC.


2
theo một số phiên bản của GCC!
Mohamed Amjad LASRI

1

Những người khác đã trả lời đầy đủ. Tôi chỉ muốn thêm một vài ví dụ về các tiện ích mở rộng thường xuyên:

Các main chức năng trở về void. Điều này không được xác định bởi tiêu chuẩn, có nghĩa là nó sẽ chỉ hoạt động trên một số trình biên dịch (bao gồm GCC), nhưng không phải trên các trình biên dịch khác. Nhân tiện, int main()int main(int, char**)là hai chữ ký mà tiêu chuẩn không xác định.

Một tiện ích mở rộng phổ biến khác có thể khai báo và định nghĩa các hàm bên trong các hàm khác:

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

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

Đây là không chuẩn. Nếu bạn muốn loại hành vi này, hãy xem C ++ 11 lambdas


0

Pedantic làm cho nó để trình biên dịch gcc từ chối tất cả các phần mở rộng GNU C không chỉ các phần mở rộng làm cho nó tương thích ANSI.


1
Điều này là rất xen kẽ. Bạn đề cập đến phần mở rộng GNU C và những phần mở rộng đó có thể và có thể không theo tiêu chuẩn ANSI. Tôi có thể có thêm thông tin liên quan đến điều này. Tôi có thể lấy những tài nguyên phù hợp ở đâu?
huahsin68
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.