2011-08-25 39 views
8

Đây là giao dịch. Tôi đã có hai biến toàn cục giống hệt nhau trong hai tệp .c khác nhau, chúng không được khai báo là extern. Vì vậy, mỗi tệp .c sẽ thấy biến riêng của nó, phải không?Hai biến có cùng tên và loại, trong hai tệp .c khác nhau, biên dịch với gcc

Nhưng tôi đã nhận được một số hành vi thực sự kỳ lạ, như thể một tệp đang đọc biến tệp khác (sau khi liên kết chúng với nhau). Thêm vòng loại 'tĩnh' vào cả hai định nghĩa biến dường như để khắc phục vấn đề này.

Vì vậy, những gì tôi thực sự tự hỏi là, chính xác những gì đã xảy ra ở đó mà không có vòng loại 'tĩnh'?

+1

Xem thêm http://stackoverflow.com/questions/1490693/định nghĩa-định nghĩa-in-c99-và-liên kết cho các khía cạnh phức tạp của liên kết extern. –

+0

@Pascal Câu trả lời của bạn thực sự là hoàn chỉnh nhất, quá tệ Tôi không thể gắn cờ nó là một trong những chấp nhận. Tôi nghĩ về bản thân mình làm một cái gì đó tương tự như những gì bạn đã làm ở đó với 'nm '. Chỉ có điều mà nói đến cái tâm của tôi về tình trạng này là nó là một lỗ hổng lớn trong tiêu chuẩn, nó thậm chí còn nói về ở đây http://www.jetcafe.org/jim/c-style.html#need_extern. Ý tôi là, ai trong địa ngục nghĩ rằng nó sẽ tốt đẹp nếu trình biên dịch giả định vòng loại 'extern'? C++ chắc chắn là địa ngục không làm giả định ngu ngốc như vậy. – johndoevodka

Trả lời

18

Vì vậy, mỗi tệp .c sẽ thấy biến riêng của nó, phải không?

Sai. Trong C, bỏ qua static từ một tuyên bố có nghĩa là liên kết extern tiềm ẩn.

Từ C Trong một Nutshell:

Các xử lý biên dịch tờ khai chức năng mà không có một specifier storage class như thể họ bao gồm các extern specifier. Tương tự, bất kỳ số nhận dạng đối tượng nào mà bạn khai báo bên ngoài tất cả các chức năng và không có trình chỉ định lớp lưu trữ có external linkage.

+0

Cảm ơn, tôi không biết điều đó. Tại sao trình biên dịch không đưa ra lỗi hoặc cảnh báo tho? – johndoevodka

+2

Chỉ để tham khảo, cả Visual Studio 2008 và GCC 4.3.5 đều tuân thủ quy tắc này. Và biên dịch lại mã bằng trình biên dịch C++ (bằng cách thay đổi thành phần mở rộng .cpp trong VC, hoặc gọi g ++ dưới linux) cho lỗi liên kết "nhiều định nghĩa". – Zac

0

Theo như tôi biết, khi bạn không chỉ định cả tĩnh lẫn extern thì nó tùy thuộc vào trình biên dịch để chọn. Và gcc trong trường hợp này đi cho extern, do đó bạn phải xác định tĩnh trong trường hợp của bạn.

tôi đã cùng một vấn đề, một vài năm trước đây :-)

1

tập tin đầu ra được tạo ra bằng cách làm cho đối tượng tập tin của tập tin cá nhân và sau đó liên kết chúng lại với nhau bằng mối liên kết. Bây giờ khi bạn có biến giống hệt nhau trong hai tệp khác nhau thì tệp riêng lẻ sẽ biên dịch không có lỗi nhưng tại thời điểm liên kết liên kết sẽ nhận được hai định nghĩa biến và tạo ra lỗi. Nhưng trong trường hợp của phạm vi tĩnh của cả hai biến hạn chế cho các tập tin như vậy, mọi thứ hoạt động tốt. Tôi hy vọng bạn sẽ thấy điều này hữu ích.

2

ALWAYS khởi tạo biến toàn cầu, sau đó trình biên dịch sẽ không xem xét liên kết của nó tự động như extern. Trình biên dịch sẽ ném lỗi trong quá trình biên dịch.

Điều này sẽ giúp tránh các vấn đề ngẫu nhiên trong cơ sở mã lớn, bởi vì mã của chúng tôi có thể sử dụng ai đó biến khác tuyên bố rằng có một số giá trị ngẫu nhiên (ở góc độ lý của chúng tôi)

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