2011-01-22 56 views
20

Từ External Variables Wiki:Tuyên bố hoặc Định nghĩa trong C

Nếu không có từ khóa extern hay một giá trị khởi có mặt, báo cáo kết quả có thể là một tuyên bố hoặc một định nghĩa. Trình biên dịch là để phân tích các mô-đun của chương trình và quyết định.

Tôi đã không thể nắm bắt đầy đủ ý nghĩa của tuyên bố này liên quan đến C. Ví dụ, nó ngụ ý rằng:

int i; 

không nhất thiết phải là một tuyên bố (như tôi đã được giả định cho đến khi bây giờ), nhưng có thể là một định nghĩa là tốt (theo định nghĩa của Định nghĩa & Tuyên bố trên cùng một trang web, không có ý định chơi chữ)?

Tóm lại, là tuyên bố trên: a. chỉ là một tuyên bố, hoặc b. khai báo + định nghĩa?

tham khảo: Variable declaration and definition

Tóm tắt các câu trả lời nhận được:

      Declaration Definition Tentative Definition Initialized 
int i; (inside a block) Yes   Yes    No    No 
int i=5; (inside a block) Yes   Yes    No    Yes(to 5) 
int i; (otherwise)   Yes   No    Yes    Yes(to 0) 
extern int i;    Yes   No    No    No 


All definitions are declarations but not vice-versa. 

Trả lời

13

Tiêu chuẩn C nói rằng

Một định nghĩa của một định danh là một tuyên bố cho nhận dạng mà rằng: cho một đối tượng, nguyên nhân lưu trữ được dành riêng cho các đối tượng đó (...)

Các định nghĩa bao gồm các khai báo, tức là, mọi định nghĩa đều nhất thiết phải là khai báo, do đó, không có ý nghĩa khi nói rằng

int i; 

không phải là tuyên bố. Nó một tuyên bố cũng xảy ra là định nghĩa. Hoặc, nó là một định nghĩa, do đó một tuyên bố.

+7

Tuy nhiên, bạn nên nhớ rằng không phải tất cả các khai báo đều là định nghĩa. –

15

Giả sử nó ở phạm vi tập tin đó là một 'định nghĩa dự kiến'. Từ 6.9.2/2 "định nghĩa đối tượng bên ngoài":

Một tuyên bố của một định danh cho một đối tượng mà có phạm vi nộp mà không có một khởi tạo, và mà không có một specifier lưu trữ-lớp hoặc với sự xác định lưu trữ lớp tĩnh , cấu thành định nghĩa dự kiến ​​ . Nếu đơn vị dịch có chứa một hoặc nhiều định nghĩa dự kiến ​​cho số nhận dạng và đơn vị dịch không chứa định nghĩa bên ngoài cho số nhận dạng đó, thì hành vi chính xác như đơn vị dịch có chứa khai báo phạm vi tệp của số đó loại hỗn hợp vào thời điểm cuối của đơn vị dịch thuật, với một initializer bằng 0.

Điều này có nghĩa rằng nó sẽ có giá trị cũng có những điều sau đây trong các đơn vị dịch:

int i = 42; 

từ mà decla khẩu phần có một khởi tạo rõ ràng, đó là định nghĩa của biến số i.

Theo như nếu việc kê khai là trong một phạm vi khối, tiêu chuẩn nói như sau (6.2.2/2 "Mối quan hệ của bộ nhận diện"):

Mỗi tuyên bố một định danh với không biểu thị mối liên hệ một thực thể duy nhất.

...

(đoạn 6) Các định danh sau đây không có mối liên hệ: ...a số nhận dạng phạm vi khối cho một đối tượng được khai báo không có lớp lưu trữ bên ngoài bộ định danh lưu trữ.

Vì vậy, trong phạm vi khối, tuyên bố cũng sẽ là định nghĩa.

+0

Giả sử nó nằm trong một khối (không phải phạm vi tệp) ...? –

+0

@crypto: đã cập nhật câu trả lời để bao gồm một khai báo phạm vi khối. –

+0

Cảm ơn câu trả lời chi tiết. Tôi đã chọn câu trả lời của Bavarious vì nó trực tiếp hơn. –

4

Trong bối cảnh biến:

  • Một tuyên bố của một biến là một tuyên bố trong đó mô tả cách biến này như thế nào. Vì vậy:

    extern int x; 
    

    trong phạm vi toàn cầu dịch để: "ở đâu đó trong các mã, có một biến gọi là x mà có kiểu int và liên kết extern Một tuyên bố là cần thiết trước khi bạn đã bao giờ đề cập đến x (Điều này cũng đi vào.. . chức năng khai báo)

  • một định nghĩa là một tuyên bố mà tạo ra một thể hiện của biến này Vì vậy:.

    int x; 
    

    trong phạm vi toàn cầu tạo ra một variab đơn le của loại int với liên kết extern. Vì vậy, nếu bạn đặt dòng đó vào tiêu đề, mọi đơn vị dịch bao gồm tiêu đề đó sẽ cố tạo bản sao x của riêng nó, điều không mong muốn - đó là lý do chúng tôi chỉ có khai báo trong tệp tiêu đề. Cũng vậy với các hàm: nếu bạn cung cấp thân hàm, nó là một định nghĩa.

Ngoài ra, chính thức, mọi định nghĩa là một loại khai báo, vì nó cũng phải chỉ định cách biến/chức năng này trông như thế nào - vì vậy nếu định nghĩa đã tồn tại trong một phạm vi nhất định, bạn không cần bất kỳ khai báo bổ sung để sử dụng nó.

1

Từ spec C99:

Một tuyên bố của một định danh cho một đối tượng mà có phạm vi nộp mà không có một khởi tạo, và mà không có một specifier lưu trữ-lớp hoặc với sự xác định lưu trữ lớp tĩnh, tạo thành một định nghĩa dự kiến.Nếu đơn vị dịch có chứa một hoặc nhiều định nghĩa dự kiến ​​cho số nhận dạng và đơn vị dịch không chứa định nghĩa bên ngoài cho số nhận dạng đó, thì hành vi chính xác như đơn vị dịch có chứa khai báo phạm vi tệp của số đó loại hỗn hợp ở cuối đơn vị dịch, với bộ khởi tạo bằng 0.

Vì vậy, đây là một trường hợp trong đó khai báo đơn giản không có bộ khởi tạo có thể là khai báo.

+0

Bạn có thể thêm câu trả lời của mình cho Michael, vì bạn đang đề cập đến cùng một phần của Tiêu chuẩn C99 không? –

+0

Trích dẫn đó từ spec là nói về hành vi của trình biên dịch. Người ta nói rằng trường hợp khai báo cụ thể này có thể là một định nghĩa. – davep

+0

Có vẻ như anh ấy đã thêm câu trả lời cho câu trả lời của mình ... –

1

Khi C sử dụng các cụm từ:

Định nghĩa "" tạo ra thứ gì đó (chiếm một số loại bộ nhớ). Nó cũng mô tả một cái gì đó. Điều này có nghĩa là "định nghĩa" cũng là một "tuyên bố".

Một "tuyên bố" chỉ mô tả điều gì đó. Ý tưởng là trình biên dịch cần biết cách xây dựng mã sử dụng thứ được định nghĩa ở nơi khác. Sau đó, trình liên kết sau đó liên kết việc sử dụng với cái gì đó.

Tuyên bố cho phép bạn biên dịch mã và liên kết mã (sau này) dưới dạng một bước riêng biệt.

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