Có nhất thiết phải tuân theo tiêu chuẩn, lấy tiêu chuẩn C cho vấn đề đó không?


17

Có một số người rất có kinh nghiệm trên Stack Overflow luôn nói về tiêu chuẩn C. Mọi người dường như không thích các giải pháp không di động, ngay cả khi chúng làm việc cho tôi. Ok, tôi hiểu rằng các tiêu chuẩn cần phải được tuân theo, nhưng nó không đặt xiềng xích cho sự sáng tạo của lập trình viên?

Những lợi ích cụ thể đến từ việc tuân theo một tiêu chuẩn là gì? Đặc biệt là các trình biên dịch có thể thực hiện các tiêu chuẩn hơi khác nhau.


7
Bạn có thể làm rõ những gì bạn có nghĩa là "tiêu chuẩn"? Bạn có nghĩa là không áp dụng lại hành vi không được xác định bởi tiêu chuẩn? Hoặc không sử dụng các tính năng mở rộng / trình biên dịch? Hoặc quy ước phong cách?
ikh

1
@ikh Ông đang lấy tiêu chuẩn ISO C (C90, C99, C11).
Aseem Bansal

9
Điều đó cũng giống như nói rằng viết hoặc nói bằng tiếng Anh, sử dụng ngữ pháp và từ vựng tiếng Anh, sẽ tạo ra xiềng xích cho sự sáng tạo của bạn. Chắc chắn, mọi người có thể làm những điều tuyệt vời bằng cách phá vỡ các quy tắc, với chi phí mạch lạc, nhưng bạn có thể viết hàng triệu cuốn sách sáng tạo trong khi vẫn tuân thủ "tiêu chuẩn" tiếng Anh.
Avner Shahar-Kashtan

bạn có thể thêm một ví dụ về "Mọi người dường như không thích các giải pháp không di động, ngay cả khi họ làm việc cho tôi"?
BЈовић

1
@PHIfounder Chỉ cần giải quyết trường hợp cuối cùng đó, bạn có thể bỏ qua việc trả lại từ chính, nó hoàn toàn trả về 0 :)
Daniel Gratzer

Câu trả lời:


45

Có một vài lý do tại sao bám sát tiêu chuẩn là một điều tốt.

  1. Bị khóa vào một trình biên dịch hút khó. Bạn hoàn toàn chịu trách nhiệm của một nhóm các nhà phát triển với chương trình nghị sự riêng của họ. Rõ ràng là họ không ra ngoài để giúp bạn hoặc bất cứ điều gì, nhưng nếu trình biên dịch của bạn bắt đầu tụt hậu về tối ưu hóa, các tính năng mới, sửa lỗi bảo mật, v.v., quá tệ; Bạn đang bị mắc kẹt. Trong trường hợp cực đoan, một số công ty phải bắt đầu vá bất cứ công cụ nào mà họ tự làm. Đây là một sự lãng phí rất lớn về tiền bạc và thời gian khi có những công cụ làm việc khác ngoài kia.

  2. Bị khóa vào một nền tảng hút khó hơn. Nếu bạn đang đẩy phần mềm trên Linux và muốn chuyển sang Windows vì bạn nhận thấy thị trường của mình thực sự ở đó, bạn sẽ có một thời gian thay đổi mọi hack không di động mà bạn có trong mã của mình để chơi tốt với cả GCC và MSVC. Nếu bạn đã có một vài phần của thiết kế cốt lõi của bạn dựa trên một cái gì đó như thế, chúc may mắn!

  3. Thay đổi ngược không tương thích hút khó nhất. Tiêu chuẩn sẽ không bao giờ phá vỡ mã của bạn (Bỏ qua python). Một số người viết trình biên dịch ngẫu nhiên mặc dù có thể quyết định rằng thực sự bổ trợ cụ thể thực hiện này không đáng để gặp rắc rối và bỏ nó. Nếu bạn tình cờ dựa vào nó, thì bạn sẽ bị mắc kẹt với bất kỳ phiên bản cũ lỗi thời nào.

Vì vậy, thông điệp ghi đè ở đây, bám sát tiêu chuẩn làm cho bạn linh hoạt hơn . Bạn có một ngôn ngữ hạn chế hơn chắc chắn, nhưng bạn có nhiều hơn

  • Thư viện
  • Hỗ trợ (mọi người biết tiêu chuẩn, không phải mọi hack cụ thể của trình biên dịch phức tạp)
  • Nền tảng có sẵn
  • Công cụ trưởng thành
  • Bảo mật (bằng chứng trong tương lai)

Đó là một sự cân bằng tinh tế, nhưng hoàn toàn bỏ qua các tiêu chuẩn chắc chắn là một sai lầm. Tôi có xu hướng tổ chức mã C của mình dựa trên các khái niệm trừu tượng có thể được triển khai theo cách không di động, nhưng tôi có thể chuyển đổi trong suốt mà không thay đổi mọi thứ phụ thuộc vào sự trừu tượng hóa.


+1 đủ công bằng :), cảm ơn ... Tôi đã nhầm lẫn nghiêm trọng về cách trình biên dịch hơi lệch khỏi các tiêu chuẩn và khiến tôi cảm thấy hoài nghi về việc tuân thủ nghiêm ngặt, cần biết những ưu và nhược điểm của nó và bạn đã xác định rõ những điều đó.
0decimal0

6
Hành vi không xác định có thể hút khá nhiều là tốt. Với c, thật dễ dàng để liên doanh vào UB nếu bạn không tuân thủ chặt chẽ tiêu chuẩn.
CodeInChaos

@CodesInChaos Đồng ý, một mặt hành vi không xác định là tuyệt vời vì nó cho phép một số tối ưu hóa điên rồ, nhưng mặt khác gỡ lỗi nó ...
Daniel Gratzer

6

Tiêu chuẩn là một loại "hợp đồng" giữa bạn và trình biên dịch xác định ý nghĩa của các chương trình của bạn. Là lập trình viên, chúng ta thường có một mô hình tinh thần nhất định về cách ngôn ngữ hoạt động, và mô hình tinh thần này thường mâu thuẫn với tiêu chuẩn. . địa chỉ. Giả định này không phù hợp với tiêu chuẩn, nó thực sự áp đặt các hạn chế rất nghiêm ngặt đối với những gì bạn có thể làm với con trỏ.)

Vì vậy, lợi thế của việc tuân theo tiêu chuẩn, hơn là mô hình tinh thần của riêng bạn là gì?

Nói một cách đơn giản, đó là tiêu chuẩn là chính xác, và mô hình tinh thần của chính bạn là sai. Mô hình tinh thần của bạn thường là một cái nhìn đơn giản về cách mọi thứ hoạt động trên hệ thống của bạn, trong các trường hợp phổ biến, với tất cả các tối ưu hóa trình biên dịch bị vô hiệu hóa; các nhà cung cấp trình biên dịch thường không nỗ lực để tuân thủ nó, đặc biệt là khi nói đến tối ưu hóa. (Nếu bạn không giữ hết hợp đồng, bạn không thể mong đợi bất kỳ hành vi cụ thể nào từ trình biên dịch: rác vào, rác ra.)

Mọi người dường như không thích các giải pháp không di động, ngay cả khi chúng làm việc cho tôi.

Có thể tốt hơn để nói, "ngay cả khi họ dường như làm việc cho tôi". Trừ khi trình biên dịch của bạn tài liệu cụ thể rằng một hành vi nhất định sẽ hoạt động (nghĩa là: trừ khi bạn đang sử dụng một tiêu chuẩn phong phú, bao gồm tài liệu trình biên dịch cộng thích hợp tiêu chuẩn), bạn không biết rằng nó thực sự hoạt động hoặc nó thực sự đáng tin cậy. Ví dụ, tràn số nguyên đã ký thường dẫn đến việc gói trên nhiều hệ thống (vì vậy, INT_MAX+1thông thường INT_MIN) - ngoại trừ trình biên dịch "biết" rằng số học số nguyên đã ký không bao giờ tràn vào chương trình C (chính xác) và thường thực hiện tối ưu hóa rất đáng ngạc nhiên dựa trên điều này " hiểu biết".


1
Bạn có thể biên dịch với -fwrapv, và sau đó bạn đang sử dụng một ngôn ngữ không chuẩn, hơi khác, trong đó số học số nguyên đã ký luôn luôn kết thúc tốt đẹp.
dùng253751

@immibis: Khi C89 được viết, theo tài liệu hợp lý của nó, phần lớn các trình biên dịch đương đại đã xác định ngữ nghĩa gói im lặng cho tràn số nguyên. Trong nhiều trường hợp, có một số loại bảo đảm về những gì xảy ra trong trường hợp tràn số nguyên có thể cho phép mã hiệu quả hơn mức có thể nếu không có các đảm bảo đó, đặc biệt là nếu các bảo đảm không đi xa đến mức bắt buộc hành vi gói chính xác [chính xác hành vi gói có thể được mô phỏng bằng toán học không dấu, nhưng ngữ nghĩa lỏng lẻo hơn nhưng vẫn đủ để đáp ứng các yêu cầu có thể cho phép mã hiệu quả hơn].
supercat

@immibis: Thật tệ khi những người sửa đổi đã có thể thuyết phục mọi người rằng các hành vi được thực hiện gần như nhất trí giữa các trình biên dịch cho một số nền tảng nhất định (hoặc trong một số trường hợp nhất trí 100%) chưa bao giờ là "tiêu chuẩn" trên các nền tảng đó, vì trong nhiều trường hợp, mất hiệu quả do phải tránh các hành vi như vậy sẽ không bị thu hồi bởi bất kỳ "tối ưu hóa" nào mà trình biên dịch có thể đạt được bằng cách thu hồi chúng.
supercat

4

Tôi hiểu rằng tiêu chuẩn cần phải được tuân theo, nhưng nó không tạo ra xiềng xích cho sự sáng tạo của lập trình viên? vẫn còn một số khác biệt trong cách các trình biên dịch khác nhau tuân theo các tiêu chuẩn. Ví dụ, tôi có thể viết một mã hoạt động, rất tốt về hiệu suất và tốc độ, tức là tất cả những gì quan trọng, nhưng vẫn không nhất thiết phải tuân thủ nghiêm ngặt các tiêu chuẩn.

Không. Tiêu chuẩn cho biết những gì được phép làm. Nếu nó không được chỉ định, bạn đang ở trong lãnh thổ hành vi không xác định, và sau đó tất cả các cược đã tắt - chương trình có thể tự do làm bất cứ điều gì.


Vì bạn đã đề cập ví dụ cụ thể về void main()vs int main(), tôi có thể cải thiện câu trả lời của mình.

void main()không phải là một khai báo tiêu chuẩn của chức năng chính. Nó có thể hoạt động trên một số trình biên dịch thông qua các phần mở rộng, nhưng nó dựa vào việc thực hiện. Ngay cả khi nó hoạt động, bạn phải kiểm tra nếu nó làm những gì bạn muốn. Vấn đề là, các nhà phát triển trình biên dịch có thể quyết định loại bỏ void main()với bản phát hành trình biên dịch tiếp theo, phá vỡ ứng dụng của bạn.

Mặt khác, tiêu chuẩn xác định rõ ràng chữ ký của main int main()và nó cho biết những gì nó nên làm.


Mặt khác, có những điều không được xác định trong tiêu chuẩn. Sau đó, một tiêu chuẩn khác có thể được áp dụng (ví dụ như POSIX). Ví dụ tốt nhất có thể là với việc thực hiện các luồng trong c ++ 03, vì các chương trình tiêu chuẩn của c ++ 03 là 1 luồng. Trong trường hợp đó, bạn buộc phải sử dụng thư viện phụ thuộc nền tảng, hoặc một cái gì đó như boost .


4
Mọi thứ mà trình biên dịch thực hiện không phải là tiêu chuẩn không phải là hành vi không xác định, các phần mở rộng của trình biên dịch được xác định rõ theo nghĩa là chúng có tính quyết định và có chủ ý. UB không.
Daniel Gratzer

@jozefg Cách nó được hỏi - rõ ràng là OP nghĩ về cách thức thực hiện của UB. Ví dụ, các chủ đề không được xác định trong c ++ 03.
Bовић

1
@deworde: Nhận xét đã bị xóa khỏi câu trả lời.
Kevin - Tái lập Monica

@jozefg Nếu một trình biên dịch cụ thể luôn bao bọc các số nguyên đã ký, nó có thể được coi là một phần mở rộng ngôn ngữ không có giấy tờ. (Tất nhiên, không có giấy tờ có nghĩa là bạn không có gì đảm bảo về việc họ không xóa tiện ích mở rộng)
user253751

-6

Đừng tuân theo các quy tắc NẾU dự án của bạn là về các dự án đặc biệt, ví dụ như dự án chính phủ hoặc quân đội, nhưng bạn cần tuân theo các quy tắc NẾU bạn đang nói về một nguồn mở hoặc dự án lớn với một nhóm phân phối.


2
không có lời giải thích, câu trả lời này có thể trở nên vô dụng trong trường hợp nếu người khác đăng một ý kiến ​​trái ngược. Ví dụ: nếu ai đó đăng một yêu cầu như "tuân theo quy tắc NẾU dự án của bạn là về các dự án đặc biệt, ví dụ như dự án chính phủ hoặc quân đội, nhưng bạn không cần tuân theo quy tắc NẾU bạn đang nói về nguồn mở ..." , làm thế nào câu trả lời này sẽ giúp người đọc chọn hai ý kiến ​​trái ngược nhau? Xem xét chỉnh sửa ing nó thành một hình dạng tốt hơn
gnat

2
Uknown: bạn sẽ ngạc nhiên khi biết có bao nhiêu tiêu chuẩn trong các dự án của chính phủ ...
Deer Hunter
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.