2010-06-22 42 views
30

Tôi đọc từ một cuốn sách về, định nghĩa dự kiến ​​rằng,Về định nghĩa dự kiến ​​

A tentative definition is any external data declaration that has no storage class specifier and no initializer. A tentative definition becomes a full definition if the end of the translation unit is reached and no definition has appeared with an initializer for the identifier

Xin giải thích những gì tuyên bố trên có nghĩa. Ngoài ra, sự khác biệt giữa Tuyên bố và Định nghĩa? Tôi bị lẫn lộn vì điều này. :( Và tại sao không chương trình này cung cấp cho một lỗi:

#include<stdio.h> 
int a;  //Tentative definition 
int a;  //similarly this declaration too. 
int main() //not getting any error with this code why its so? 
{ 
    printf("hi"); 
} 

Ngoài ra, những gì là sai với mã này:

#include<stdio.h> 
printf("Hi"); 
int main(void){ 
    return 0; 
} 
+1

Trong sách bạn đọc về định nghĩa dự kiến? – Destructor

Trả lời

55

Một biến khai báo nói rằng "có một biến có tên và loại sau trong chương trình".

Biến số định nghĩa nói, "Thưa ông Compiler, vui lòng cấp phát bộ nhớ cho một biến có tên và loại sau ngay bây giờ".

Vì vậy, có thể có nhiều khai báo cho cùng một biến, nhưng chỉ nên có một định nghĩa.

Trong C, khai báo thuần túy (không phải là định nghĩa) được đặt trước với từ khóa extern. Vì vậy, vì bạn không có từ khóa này trong ví dụ đầu tiên của bạn, những gì bạn có là hai định nghĩa. Trên khuôn mặt của nó, điều này có vẻ là một vấn đề (và thực tế là một lỗi trong C++), nhưng C có một quy tắc "định nghĩa dự kiến" đặc biệt cho phép nhiều định nghĩa cho cùng một biến miễn là chúng phù hợp và nhiều nhất có một bộ khởi tạo. Trình biên dịch C, đằng sau hậu trường, kết hợp tất cả các định nghĩa dự kiến ​​vào một định nghĩa duy nhất.

Đã mà bạn cố gắng khởi tạo cả hai định nghĩa, như thế này:

int a = 1; 
int a = 2; 

Sau đó, bạn sẽ có một lỗi.

Câu hỏi thứ hai của bạn đơn giản hơn. Trong C, bạn chỉ đơn giản là không thể có các câu lệnh thi hành bên ngoài phần thân của một hàm. Nó không được phép. Hãy suy nghĩ về nó: khi nào bạn mong đợi nó sẽ chạy nếu nó được cho phép?

+0

@TylerMcHenry: Đó là bất hợp pháp trong cả C và C++ nhưng trình biên dịch C thực hiện điều này như là một phần mở rộng phổ biến. Xem [câu trả lời này] (http://stackoverflow.com/a/6371156/183120). – legends2k

+4

@ legends2k Không, điều này không phải là bất hợp pháp trong C ... trong câu hỏi mà bạn liên kết đến (và cũng là câu hỏi mà câu trả lời bạn liên kết đến liên kết đến) liên quan đến nhiều tệp. Định nghĩa dự kiến ​​nhiều (tương thích) trong cùng một tệp không phải là vi phạm. Vi phạm trong câu hỏi đó xảy ra bởi vì, ở phần cuối của đơn vị dịch thuật, nếu có định nghĩa dự kiến ​​không có định nghĩa đầy đủ, nghĩa là một định nghĩa đầy đủ được ngụ ý.Điều đó cộng với nhiều tệp dẫn đến nhiều định nghĩa tại thời gian liên kết (ngoại trừ phần mở rộng phổ biến của các quy tắc định nghĩa dự kiến ​​để mở rộng nhiều tệp). –

+0

Tại sao nó chỉ hợp pháp với các biến toàn cục, không phải với các biến cục bộ? Với các biến cục bộ, nó cho lỗi redeclaration? –

8

Các công trình đầu tiên vì cả hai định nghĩa lại a là dự kiến, mà Ở cuối đơn vị dịch thuật, không có định nghĩa không dự kiến ​​nào được nhìn thấy, vì vậy những gì bạn đã chỉ định cho thuộc tính được kết hợp với mặc định để đưa ra định nghĩa cuối cùng là a, do đó, nó sẽ có liên kết bên ngoài, thời lượng lưu trữ tĩnh và được khởi tạo thành 0.

Vấn đề với vấn đề thứ hai không liên quan gì đến định nghĩa dự kiến. printf("Hi"); của bạn cần phải ở bên trong một hàm để hoạt động - nó không phải là một tuyên bố hay một định nghĩa (dự kiến ​​hay cách khác); nó không được phép ở đó.

Các vấn đề liên quan