@msc giới thiệu tốt về các quy tắc đằng sau hành vi này.
Tôi nhận thấy rằng nếu tôi khai báo một biến toàn cục nhiều lần thì trình biên dịch thậm chí không đưa ra cảnh báo.
C có ba loại khai báo toàn cầu cho các đối tượng, cụ thể là các khai báo (và tôi đang trình bày static
ở đây):
- khai báo không phải là định nghĩa -
extern int a;
- khai báo cũng là định nghĩa -
int a = 3;
hoặcextern int a = 3;
- định nghĩa dự kiến -
int a;
Nhiều khai báo loại 1 & 3 được cho phép, trong khi tối đa một định nghĩa (loại 2) được cho phép.
Giải thích cho hành vi này là gì?
Nếu bạn cũng đang hỏi về động lực cho các quy tắc này, thì đó là hỗ trợ cho việc biên dịch riêng . (Xem đơn vị dịch thuật ).
Để chia một chương trình thành nhiều tệp được biên dịch riêng biệt, chúng tôi cần một vài tính năng, cụ thể là (a) có thể khai báo mà không nhất thiết phải xác định và (b) khai báo chuyển tiếp .
Trong một đơn vị dịch thuật, chúng tôi cần có thể tham khảo các chức năng và dữ liệu toàn cầu trong một đơn vị dịch thuật khác. Và chúng tôi cũng muốn một số kiểm tra lỗi, ở đây, để khám phá các định nghĩa bị thiếu và các định nghĩa trùng lặp sai.
Đôi khi, trong cùng một đơn vị dịch thuật, chúng tôi khai báo toàn cầu và sau đó xác định nó sau. Điều này có thể xảy ra nếu chúng ta cần một tuyên bố chuyển tiếp vì một số lý do hoặc nếu chúng ta sử dụng tệp tiêu đề chung (cung cấp khai báo) trong một đơn vị dịch thuật cũng cung cấp các định nghĩa rõ ràng.
Do việc biên dịch riêng biệt trong C áp dụng bằng cách liên kết các chức năng và dữ liệu toàn cầu với nhau, các tính năng này được yêu cầu ở cấp toàn cầu nhưng không phải ở cấp địa phương.
Như @msc chỉ ra, không có điều này là cần thiết cho các biến cục bộ vì chúng không có liên kết.
C (giống như nhiều ngôn ngữ khác) không cung cấp liên kết cho các biến cục bộ vì ngôn ngữ không cố gắng hỗ trợ một hàm duy nhất bao gồm nhiều đơn vị dịch riêng biệt.
(Tất nhiên, bạn có thể có một hàm trải rộng nhiều tệp nguồn, nhưng không có nhiều đơn vị dịch.)
Một định nghĩa dự kiến hoạt động giống như một tuyên bố ở chỗ nó được phép trong nhiều đơn vị dịch thuật (và cũng kết hợp độc đáo với các khai báo khác). Tuy nhiên, nếu không có định nghĩa (không dự kiến) cho mã định danh trong toàn bộ chương trình, thì tập hợp (một hoặc nhiều) định nghĩa dự kiến trên nhiều đơn vị dịch (đối với một định danh) được lấy làm định nghĩa cho đối tượng có trình khởi tạo số không.
Điều này có thể được thực hiện bằng cách đưa chúng vào Phần .BSS với kích thước và căn chỉnh phù hợp; trình liên kết sẽ khớp chúng với định nghĩa thực nếu được tìm thấy, hoặc nếu không thì khớp chúng với nhau, tạo cho chúng khoảng trống trong BSS.
Khái niệm biên dịch riêng biệt có thể được hỗ trợ hoàn toàn mà không có tính năng của các định nghĩa dự kiến - Tôi nghĩ rằng các định nghĩa dự kiến chủ yếu là vì lý do lịch sử. (Tôi không nói rằng chúng không hữu ích, chỉ cần ngôn ngữ được tạo ra ngày hôm nay, điều này có thể được xem là không cần thiết và do đó không được cung cấp.)