Câu trả lời:
Được sử dụng đúng cách, đây có thể là một kỹ thuật hữu ích.
Giả sử bạn có một hệ thống con quan trọng về hiệu suất, phức tạp với giao diện công khai khá nhỏ và rất nhiều mã triển khai không thể tái sử dụng. Mã chạy tới vài nghìn dòng, hàng trăm chức năng riêng tư và khá nhiều dữ liệu riêng tư. Nếu bạn làm việc với các hệ thống nhúng không tầm thường, bạn có thể đối phó với tình huống này đủ thường xuyên.
Giải pháp của bạn có thể sẽ được phân lớp, mô-đun và tách rời và những khía cạnh này có thể được biểu diễn và củng cố hữu ích bằng cách mã hóa các phần khác nhau của hệ thống con trong các tệp khác nhau.
Với C, bạn có thể mất rất nhiều khi làm điều này. Hầu như tất cả các toolchains đều cung cấp khả năng tối ưu hóa tốt cho một đơn vị biên dịch duy nhất, nhưng rất bi quan về bất kỳ thứ gì được tuyên bố bên ngoài.
Nếu bạn đặt mọi thứ vào một mô-đun nguồn C, bạn sẽ nhận được -
Cải thiện hiệu suất và kích thước mã - các lệnh gọi hàm sẽ được nội tuyến trong nhiều trường hợp. Ngay cả khi không có nội tuyến, trình biên dịch vẫn có cơ hội tạo ra mã hiệu quả hơn.
Dữ liệu mức liên kết & ẩn chức năng.
Tránh ô nhiễm không gian tên và hệ quả của nó - bạn có thể sử dụng các tên ít khó sử dụng hơn.
Biên dịch và liên kết nhanh hơn.
Nhưng bạn cũng gặp phải một mớ hỗn độn đáng sợ khi chỉnh sửa tệp này và bạn mất đi tính mô đun ngụ ý. Điều này có thể được khắc phục bằng cách chia nguồn thành nhiều tệp và bao gồm các tệp này để tạo ra một đơn vị biên dịch duy nhất.
Tuy nhiên, bạn cần phải áp đặt một số quy ước để quản lý việc này một cách hợp lý. Những điều này sẽ phụ thuộc vào chuỗi công cụ của bạn ở một mức độ nào đó, nhưng một số gợi ý chung là:
Đặt giao diện công khai trong một tệp tiêu đề riêng biệt - bạn vẫn nên làm điều này.
Có một tệp .c chính bao gồm tất cả các tệp .c phụ. Điều này cũng có thể bao gồm mã cho giao diện công cộng.
Sử dụng trình bảo vệ trình biên dịch để đảm bảo rằng các tiêu đề riêng và mô-đun nguồn không được các đơn vị biên dịch bên ngoài đưa vào.
Tất cả dữ liệu và chức năng riêng tư nên được khai báo tĩnh.
Duy trì sự khác biệt về khái niệm giữa các tệp .c và .h. Điều này thúc đẩy các quy ước hiện có. Sự khác biệt là bạn sẽ có rất nhiều khai báo tĩnh trong tiêu đề của mình.
Nếu chuỗi công cụ của bạn không áp đặt bất kỳ lý do gì, hãy đặt tên cho các tệp triển khai riêng tư là .c và .h. Nếu bạn sử dụng các bảo vệ bao gồm, chúng sẽ không tạo ra mã và không giới thiệu tên mới (bạn có thể kết thúc với một số phân đoạn trống trong quá trình liên kết). Ưu điểm rất lớn là các công cụ khác (ví dụ như IDE) sẽ xử lý các tệp này một cách thích hợp.
Là nó ổn? vâng, nó sẽ biên dịch
nó được khuyến khích? không - tệp .c biên dịch thành tệp .obj, được liên kết với nhau sau khi biên dịch (bởi trình liên kết) thành tệp thực thi (hoặc thư viện), vì vậy không cần bao gồm tệp .c này vào tệp khác. Thay vào đó, điều bạn có thể muốn làm là tạo tệp .h liệt kê các hàm / biến có sẵn trong tệp .c khác và bao gồm tệp .h
Không.
Tùy thuộc vào môi trường xây dựng của bạn (bạn không chỉ định), bạn có thể thấy rằng nó hoạt động chính xác theo cách bạn muốn.
Tuy nhiên, có nhiều môi trường (cả IDE và rất nhiều Makefiles được làm thủ công) mong muốn biên dịch * .c - nếu điều đó xảy ra, bạn có thể sẽ gặp phải lỗi trình liên kết do các ký hiệu trùng lặp.
Theo quy định, thực hành này nên tránh.
Nếu bạn hoàn toàn phải #include source (và nói chung là nên tránh), hãy sử dụng một hậu tố tệp khác cho tệp.
Tôi nghĩ rằng tôi sẽ chia sẻ một tình huống mà nhóm của tôi quyết định bao gồm các tệp .c. Hình ảnh của chúng tôi chủ yếu bao gồm các mô-đun được phân tách thông qua một hệ thống tin nhắn. Các trình xử lý thông báo này là công khai và gọi nhiều hàm static worker cục bộ để thực hiện công việc của chúng. Vấn đề đã xảy ra khi cố gắng đưa vào các trường hợp thử nghiệm đơn vị của chúng tôi, vì cách duy nhất để thực hiện mã triển khai riêng tư này là gián tiếp thông qua giao diện thông báo công khai. Với một số chức năng của công nhân nằm sâu trong ngăn xếp, điều này hóa ra là một cơn ác mộng để đạt được độ bao phủ thích hợp.
Bao gồm các tệp .c đã cho chúng tôi một cách để tiếp cận bánh răng trong chiếc máy mà chúng tôi rất thú vị khi thử nghiệm.
Bạn có thể sử dụng trình biên dịch gcc trong linux để liên kết hai tệp c trong một đầu ra. Giả sử bạn có hai tệp c, một là 'main.c' và một là 'support.c'. Vì vậy, lệnh để liên kết hai điều này là
gcc main.c support.c -o main.out
Bằng cách này, hai tệp sẽ được liên kết với một đầu ra main.out Để chạy đầu ra, lệnh sẽ
./main.out
Nếu bạn đang sử dụng hàm trong main.c được khai báo trong tệp support.c thì bạn nên khai báo nó trong main cũng bằng cách sử dụng lớp lưu trữ bên ngoài.
Bạn có thể bao gồm đúng cách các tệp .C hoặc .CPP vào các tệp nguồn khác. Tùy thuộc vào IDE của bạn, bạn thường có thể ngăn liên kết kép bằng cách xem các thuộc tính tệp nguồn mà bạn muốn đưa vào, thường bằng cách nhấp chuột phải vào nó và nhấp vào thuộc tính, và bỏ chọn / kiểm tra biên dịch / liên kết / loại trừ khỏi bản dựng hoặc bất kỳ tùy chọn nào. có lẽ. Hoặc bạn không thể bao gồm tệp trong chính dự án, do đó IDE thậm chí sẽ không biết nó tồn tại và sẽ không cố gắng biên dịch nó. Và với các tệp makefiles, bạn chỉ đơn giản là sẽ không đưa tệp vào đó để biên dịch và liên kết.
CHỈNH SỬA: Xin lỗi, tôi đã biến nó thành một câu trả lời thay vì một câu trả lời cho các câu trả lời khác :(
Ngôn ngữ C không cấm loại #include đó, nhưng đơn vị dịch kết quả vẫn phải là C.
Tôi không biết bạn đang sử dụng chương trình nào với tệp .prj. Nếu bạn đang sử dụng một cái gì đó như "make" hoặc Visual Studio hoặc bất cứ thứ gì, chỉ cần đảm bảo rằng bạn đặt danh sách tệp được biên dịch mà không có tệp không thể biên dịch độc lập.
Bao gồm tệp C vào một tệp khác là hợp pháp, nhưng điều không nên làm, trừ khi bạn biết chính xác tại sao bạn làm điều này và bạn đang cố gắng đạt được điều gì.
Tôi gần như chắc chắn rằng nếu bạn đăng ở đây lý do đằng sau câu hỏi của bạn, cộng đồng sẽ tìm cho bạn một cách khác thích hợp hơn để đạt được mục tiêu của bạn (vui lòng lưu ý "hầu như", vì có thể đây là giải pháp cho bối cảnh ).
Nhân tiện, tôi đã bỏ lỡ phần thứ hai của câu hỏi. Nếu tệp C được đưa vào tệp khác và đồng thời được đưa vào dự án, bạn có thể sẽ gặp phải vấn đề trùng lặp biểu tượng tại sao lại liên kết các đối tượng, tức là cùng một hàm sẽ được xác định hai lần (trừ khi tất cả chúng đều tĩnh).