2013-08-09 26 views
6

Tôi không thể hiểu tại sao điều này không hoạt động.Thứ tự `định nghĩa tĩnh` và `khai báo extern` trong một đơn vị dịch

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

static int i =3; 

Ngoài ra, điều này không làm việc:

extern int i; 

static int i =3; 

int main() 
{ 
    printf(" %d ", i); 
} 

Nhưng nếu static biến được xác định trước extern declaration nó hoạt động:

static int i =3; 

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

Theo tôi được biết từ extern int i nói rằng i là hiện tại ở một nơi khác và tại đây trông như thế nào (int i)

Nhưng, ở một nơi khác phương tiện:

1) Có lẽ, điểm sau trong đơn vị same dịch như một global variable.

2) Có thể, trong một số đơn vị dịch là other.

Tôi đã nghĩ rằng (1) sẽ hợp lệ mặc dù static int i = 3 đã hạn chế phạm vi của i đối với đơn vị dịch hiện tại mà nó được xác định.

Không phải là static int i =3global (tôi có nghĩa là ít nhất nó có thể nhìn thấy trong đơn vị dịch) ở đây mặc dù nó có phạm vi giới hạn đối với đơn vị dịch thuật của nó? Vậy tại sao trình biên dịch không thể tìm thấy nó?

Khi tôi biên dịch hai phiên bản đầu tiên tôi nhận được lỗi thời gian biên dịch sau:

error: static declaration of ‘i’ follows non-static declaration 
note: previous declaration of ‘i’ was here 

Tôi không thể hiểu được thông báo lỗi này. Ngoài ra, tại sao nó phàn nàn nó như là một tĩnh declaration nó không phải là một definition cũng?

+0

Chính xác "không hoạt động" là gì? Nó là một vấn đề biên dịch? Vấn đề thời gian chạy? Tôi đang biên dịch mã của bạn với VS 2010 và có vẻ như nó hoạt động tốt. – Nbr44

+0

ComIPler GCC, tôi nhận được một biên dịch lỗi thời gian khai báo tĩnh của i sau tuyên bố không tĩnh. –

Trả lời

6

C11 6.2.2 mối liên kết của định danh Phần 4

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

Vì vậy, việc kê khai thứ hai sẽ làm theo các đầu tiên, trở lại ví dụ của bạn, 1 và 2 ví dụ i sẽ có một kho lưu extern. Trình biên dịch nghĩ rằng đó là một lỗi.

Trong khi ở ví dụ thứ 3, i sẽ là static vì trước tiên static hiển thị. Đó không phải là vấn đề.

Và, trong Phần 7 của C11 6.2.2 mối liên kết của định danh

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

Vì vậy, nó là tốt hơn không phải khai báo các biến tương tự với cả hai staticextern trong các đơn vị dịch tương tự.

+0

Có, tôi đồng ý. Nhưng điều gì khiến tôi lo lắng là tại sao phiên bản '3'rd' luôn luôn hoạt động? Trên nhiều trình biên dịch. –

+0

@UchiaItachi: Tại sao bạn lo lắng về phiên bản thứ ba? Câu trả lời này trích dẫn văn bản từ tiêu chuẩn C giải thích nó: Khi khai báo 'extern' sau một khai báo có liên kết bên trong (' static') hoặc bên ngoài, khai báo trước được sử dụng. –

+0

@UchiaItachi Đối với một điều, ngay cả khi bạn đã thử nghiệm tất cả các trình biên dịch mà rõ ràng bạn không thể, và nó tất cả các công trình, điều đó không có nghĩa là nó được xác định hành vi. Tiêu chuẩn là một trong những quyết định. –

2

Vâng, một biến là extern hoặc static. Hãy nhớ rằng static ở cấp độ toàn cầu chỉ hạn chế khả năng hiển thị của nó đối với đơn vị dịch hiện tại, trong khi extern chỉ ra rằng nó hiển thị trên các đơn vị dịch khác nhau.

+0

Tôi biết rằng 'static' rescrits khả năng hiển thị và' extern' có thể dicate trên các đơn vị dịch khác 'bao gồm' hiện tại. Nhưng mã hoạt động nếu tôi định nghĩa biến tĩnh trước và đưa ra một khai báo extern chứng minh rằng nó có 'static' và' extern'. –

+0

Điều này thực sự đã khiến tôi bối rối, nhưng lời giải thích duy nhất của tôi chính là thông báo lỗi: 'khai báo tĩnh của‘ i ’theo sau khai báo không tĩnh”. Theo tôi hiểu nó 'static' phải đứng trước bất kỳ khai báo không tĩnh nào. Và do thời gian 'extern' đạt tới, đã có một định nghĩa' 'mà' extern' hài lòng. – Nobilis

0

Không có nghĩa lý gì khi tuyên bố một cái gì đó là static và một lần nữa là extern. Làm như vậy là hành vi không xác định, do đó, không làm điều đó.

+0

Nhưng không phải là lý do tại sao 'extern' tuyên bố là có cho? Để nói rằng nó được xác định thêm xuống tập tin? Và tôi biết rằng mã của bạn hoạt động như tôi đã đề cập trong câu hỏi của tôi. –

+0

@UchiaItachi, chỉnh sửa câu trả lời của tôi, nó là chính xác ngay bây giờ. Đó là hành vi không xác định. –

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