Đầu tiên, tôi sẽ lưu ý rằng mặc dù tôi chỉ đề cập đến "C" ở đây, điều tương tự cũng thực sự áp dụng tương tự với C ++.
Nhận xét đề cập đến Godel là một phần (nhưng chỉ một phần) về điểm.
Khi bạn đi xuống, hành vi không xác định trong các tiêu chuẩn C phần lớn chỉ là chỉ ra ranh giới giữa những gì các tiêu chuẩn cố gắng xác định và những gì nó không.
Các định lý của Godel (có hai) về cơ bản nói rằng không thể định nghĩa một hệ thống toán học có thể được chứng minh (bằng các quy tắc riêng của nó) để hoàn chỉnh và nhất quán. Bạn có thể đưa ra các quy tắc của mình để có thể hoàn thành (trường hợp anh ấy xử lý là quy tắc "bình thường" cho các số tự nhiên) hoặc nếu không bạn có thể chứng minh tính nhất quán của nó, nhưng bạn không thể có cả hai.
Trong trường hợp của một cái gì đó như C, điều đó không áp dụng trực tiếp - đối với hầu hết các phần, "khả năng chứng minh" về tính hoàn chỉnh hoặc tính nhất quán của hệ thống không phải là ưu tiên cao đối với hầu hết các nhà thiết kế ngôn ngữ. Đồng thời, vâng, có lẽ họ đã bị ảnh hưởng (ít nhất là ở một mức độ nào đó) khi biết rằng không thể xác định một hệ thống "hoàn hảo" - một hệ thống hoàn toàn có thể chứng minh được. Biết rằng một điều như vậy là không thể có thể làm cho việc lùi lại, thở một chút và quyết định giới hạn của những gì họ sẽ cố gắng xác định sẽ dễ dàng hơn một chút.
Có nguy cơ (một lần nữa) bị buộc tội kiêu ngạo, tôi mô tả tiêu chuẩn C là bị chi phối (một phần) bởi hai ý tưởng cơ bản:
- Ngôn ngữ nên hỗ trợ càng nhiều phần cứng càng tốt (lý tưởng nhất là tất cả phần cứng "lành mạnh" xuống giới hạn thấp hơn hợp lý).
- Ngôn ngữ nên hỗ trợ viết càng nhiều phần mềm càng tốt cho môi trường nhất định.
Điều đầu tiên có nghĩa là nếu ai đó định nghĩa một CPU mới, thì có thể cung cấp một triển khai C tốt, chắc chắn, có thể sử dụng được cho điều đó, miễn là thiết kế rơi ít nhất là gần với một vài hướng dẫn đơn giản - về cơ bản, nếu nó tuân theo thứ gì đó theo thứ tự chung của mô hình Von Neumann và cung cấp ít nhất một lượng bộ nhớ tối thiểu hợp lý, đủ để cho phép thực hiện C. Để triển khai "được lưu trữ" (một chương trình chạy trên HĐH), bạn cần hỗ trợ một số khái niệm tương ứng chặt chẽ với các tệp và có một bộ ký tự với một bộ ký tự tối thiểu nhất định (yêu cầu 91).
Thứ hai có nghĩa là có thể viết mã thao tác trực tiếp với phần cứng, do đó bạn có thể viết những thứ như bộ tải khởi động, hệ điều hành, phần mềm nhúng chạy mà không cần bất kỳ HĐH nào, v.v ... Cuối cùng cũng có một số giới hạn hệ thống thực tiễn điều hành, bộ nạp khởi động, vv, là khả năng chứa ít nhất một chút chút mã viết bằng ngôn ngữ lắp ráp. Tương tự như vậy, ngay cả một hệ thống nhúng nhỏ cũng có khả năng bao gồm ít nhất một số loại thói quen thư viện được viết sẵn để cấp quyền truy cập vào các thiết bị trên hệ thống máy chủ. Mặc dù một ranh giới chính xác rất khó xác định, mục đích là sự phụ thuộc vào mã đó phải được giữ ở mức tối thiểu.
Hành vi không xác định trong ngôn ngữ chủ yếu được thúc đẩy bởi ý định cho ngôn ngữ hỗ trợ các khả năng này. Ví dụ: ngôn ngữ cho phép bạn chuyển đổi một số nguyên tùy ý thành một con trỏ và truy cập bất cứ điều gì xảy ra tại địa chỉ đó. Tiêu chuẩn không cố gắng nói điều gì sẽ xảy ra khi bạn làm (ví dụ, thậm chí đọc từ một số địa chỉ có thể có ảnh hưởng bên ngoài). Đồng thời, nó không cố gắng ngăn bạn làm những việc như vậy, bởi vì bạn cần phải có một số loại phần mềm mà bạn có thể viết bằng C.
Có một số hành vi không xác định được thúc đẩy bởi các yếu tố thiết kế khác là tốt. Ví dụ, một mục đích khác của C là hỗ trợ biên dịch riêng. Điều này có nghĩa (ví dụ) rằng nó có ý định rằng bạn có thể "liên kết" các mảnh lại với nhau bằng cách sử dụng một trình liên kết theo hầu hết những gì chúng ta xem là mô hình thông thường của trình liên kết. Cụ thể, có thể kết hợp các mô-đun được biên dịch riêng biệt thành một chương trình hoàn chỉnh mà không cần biết về ngữ nghĩa của ngôn ngữ.
Có một loại hành vi không xác định khác (phổ biến hơn nhiều trong C ++ so với C), hiện diện đơn giản là do các giới hạn về công nghệ trình biên dịch - những điều mà về cơ bản chúng ta biết là lỗi và có thể muốn trình biên dịch chẩn đoán là lỗi, nhưng với các giới hạn hiện tại về công nghệ trình biên dịch, điều đáng nghi ngờ là chúng có thể được chẩn đoán trong mọi trường hợp. Nhiều trong số này được điều khiển bởi các yêu cầu khác, chẳng hạn như để biên dịch riêng biệt, do đó, phần lớn là vấn đề cân bằng các yêu cầu xung đột, trong trường hợp ủy ban thường chọn hỗ trợ các khả năng lớn hơn, ngay cả khi điều đó có nghĩa là thiếu chẩn đoán một số vấn đề có thể xảy ra, thay vì giới hạn các khả năng để đảm bảo rằng tất cả các vấn đề có thể được chẩn đoán.
Những khác biệt về ý định này thúc đẩy hầu hết sự khác biệt giữa C và một cái gì đó như Java hoặc các hệ thống dựa trên CLI của Microsoft. Cái sau khá hạn chế để làm việc với một bộ phần cứng hạn chế hơn nhiều, hoặc yêu cầu phần mềm phải mô phỏng phần cứng cụ thể hơn mà chúng nhắm tới. Họ cũng đặc biệt có ý định ngăn chặn mọi thao tác trực tiếp đối với phần cứng, thay vào đó yêu cầu bạn sử dụng một cái gì đó như JNI hoặc P / Gọi (và mã được viết bằng thứ gì đó như C) để thực hiện một nỗ lực như vậy.
Quay trở lại các định lý của Godel một lúc, chúng ta có thể rút ra một điều song song: Java và CLI đã chọn phương án "nhất quán nội bộ", trong khi C đã chọn phương án "hoàn chỉnh". Tất nhiên, đây là một loại suy rất thô - Tôi nghi ngờ ai ấy cố gắng một bằng chứng chính thức hoặc là nhất quán nội bộ hoặc tính đầy đủ trong cả hai trường hợp. Tuy nhiên, khái niệm chung không phù hợp khá chặt chẽ với những lựa chọn mà họ đã thực hiện.