2010-05-15 40 views
46

Tại sao extern int n không biên dịch khi n được khai báo (trong một tệp khác) static int n, nhưng hoạt động khi được khai báo int n? (Cả hai tờ khai này đều nằm trong phạm vi tệp.)Tại sao bên ngoài không liên kết với biến tĩnh?

Về cơ bản, tại sao là int n trong phạm vi tệp không giống như static int n trong cùng phạm vi? Nó chỉ liên quan đến extern? Nếu vậy, những gì về extern tôi bị mất?

Trả lời

97

Toàn bộ và toàn bộ mục đích của static là tuyên bố rằng một biến là riêng tư đối với tệp nguồn được khai báo trong. Vì vậy, nó đang làm chính xác công việc của nó trong việc ngăn chặn một kết nối từ một extern.

Hãy ghi nhớ rằng có bốn hương vị của định nghĩa biến file-phạm vi:

  1. int blah = 0; - blah được định nghĩa trong tập tin này và truy cập từ các file khác. Định nghĩa trong các tệp khác là trùng lặp và sẽ dẫn đến lỗi.
  2. extern int blah; - blah phải được xác định ở nơi khác và được tham chiếu từ tệp này.
  3. int blah; - Đây là tương đương đạo đức của FORTRAN COMMON. Bạn có thể có bất kỳ số nào trong số này trong các tệp và tất cả chúng được giải quyết bởi trình liên kết đến một tệp được chia sẻ int. (*)
  4. static int blah; (tùy chọn với bộ khởi tạo) - Đây là tĩnh. Nó hoàn toàn riêng tư đối với tệp này. Nó không hiển thị với các tệp bên ngoài trong các tệp khác và bạn có thể có nhiều tệp khác nhau, tất cả đều khai báo static TYPE blah; và tất cả chúng đều là khác nhau.

Đối với người thuần túy trong đối tượng: 'file' = đơn vị biên dịch.

Lưu ý rằng các chức năng bên trong tĩnh (không nằm trong phạm vi tệp) thậm chí còn được sắp xếp chặt chẽ hơn: nếu hai hàm khai báo static int bleh = 0; ngay cả trong cùng một tệp, chúng không liên quan.

(*): đối với những người bạn không quen thuộc: trong mẫu thông thường, một đơn vị biên dịch phải xác định biến toàn cục và một số khác có thể tham chiếu. Nó 'sống' trong đơn vị biên dịch đó. Trong trường hợp (3), ở trên, không có tập tin (hoặc tất cả các tập tin) định nghĩa nó. Nếu hai tệp nói int blah = 0;, trình liên kết sẽ khiếu nại nhiều định nghĩa. Nếu hai tệp cho biết int blah;, trình liên kết vui vẻ tạo ra một đơn lẻ toàn cầu int và làm cho tất cả mã đề cập đến nó.

+0

những gì sau đó sẽ 'int n' được gọi là (trong phạm vi tệp), về mặt bộ nhớ lưu trữ? –

+0

@bmargulies: Ở phạm vi tệp, ý của bạn là gì? Vì tại phạm vi hàm, một var tĩnh là một giá trị giữ lại giá trị của nó sau khi các hàm trả về, và ở phạm vi lớp, một thành viên tĩnh có một cá thể duy nhất có sẵn cho tất cả các đối tượng. – mingos

+0

Làm rõ bằng bản chỉnh sửa, tôi tin tưởng. – bmargulies

5

Trong tiêu chuẩn C, có hai phạm vi cho các biến được khai báo bên ngoài một hàm. Biến số static chỉ hiển thị bên trong đơn vị biên dịch (tức là, tệp) đã khai báo nó và các biến không tĩnh hiển thị trên toàn bộ chương trình. Tuyên bố extern nói rằng vị trí của biến chưa được biết, nhưng sẽ được sắp xếp bởi trình liên kết; nó tương thích với các biến không tĩnh, nhưng extern static chỉ là nói chuyện điên rồ!

Tất nhiên, trong thực tế, có những sự linh hoạt khác trong những ngày này. Đặc biệt, hiện nay có các cấp độ phạm vi giữa một tệp nguồn duy nhất và toàn bộ chương trình; mức độ của một thư viện được chia sẻ duy nhất là một thư viện hữu ích (có thể đặt qua các cơ chế như thuộc tính hàm GCC). Nhưng đó chỉ là một biến thể về chủ đề của các biến không tĩnh; static giữ nguyên cách giải thích tương tự trước đó.

0

Theo tài liệu MSDN:

When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).

http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx: Tháng 6 năm 2013

1

IV.C: 2: 1: lỗi: nhiều lớp lưu trữ trong specifiers khai extern static int i; ^

Đó là những gì chúng tôi nhận được khi cố gắng loại bỏ biến tĩnh. Khai báo extern static int i; - tương tự với khai báo float int i; Bạn không thể có float và int xuất hiện trong cùng một tuyên bố đúng không? Tương tự, bạn không thể có extern và static trong cùng một khai báo.

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