2013-07-02 31 views
36

Đôi khi tôi nhìn thấy ai đó biên dịch một chương trình C như thế này:Tôi có cần biên dịch các tệp tiêu đề trong chương trình C không?

gcc -o hello hello.c hello.h

Như tôi biết, chúng ta chỉ cần đặt các tập tin tiêu đề vào chương trình C như:

#include "somefile"

và biên dịch chương trình C: gcc -o hello hello.c.

Khi nào chúng tôi cần biên dịch các tệp tiêu đề hoặc tại sao?

+0

Giả sử bạn chưa viết hello.c, nhưng bạn có tệp tiêu đề. Sau đó, bạn có thể sử dụng "gcc hello.h" để kiểm tra tệp tiêu đề cho các lỗi cú pháp. Nếu không, bạn phải tạo một tệp nguồn với một câu lệnh include cho hello.h (well ... Tôi đoán bạn sẽ phải làm điều đó anyway tại một số điểm). – Mark

Trả lời

23

Thứ nhất, nói chung:

Nếu những .h file có thực sự điển hình C-style tập tin tiêu đề (như trái ngược với một cái gì đó hoàn toàn khác nhau mà chỉ xảy ra được đặt tên với .h mở rộng), thì không có, không có lý do để "biên dịch" các tệp tiêu đề này một cách độc lập. Các tệp tiêu đề được dự định sẽ được đưa vào các tệp triển khai, không được đưa vào trình biên dịch dưới dạng các đơn vị dịch độc lập.

Vì tệp tiêu đề điển hình thường chỉ chứa các khai báo có thể được lặp lại một cách an toàn trong mỗi đơn vị dịch, hoàn toàn mong đợi rằng "biên dịch" một tệp tiêu đề sẽ không có hậu quả có hại. Nhưng đồng thời nó sẽ không đạt được bất cứ điều gì hữu ích.

Về cơ bản, biên soạn hello.h như một đơn vị dịch độc lập tương đương với việc tạo ra một tập tin thoái hóa dummy.c gồm duy nhất của #include "hello.h" chỉ thị, và ăn mà dummy.c tập tin vào trình biên dịch. Nó sẽ biên dịch, nhưng nó sẽ không phục vụ mục đích có ý nghĩa.


Thứ hai, đặc biệt cho GCC:

Nhiều trình biên dịch sẽ đối xử với các file khác nhau tùy thuộc vào phần mở rộng tên tập tin. GCC có cách xử lý đặc biệt cho các tệp có phần mở rộng .h khi chúng được cung cấp cho trình biên dịch dưới dạng đối số dòng lệnh. Thay vì xử lý nó như một đơn vị dịch thuật thông thường, GCC tạo ra một tiêu đề được biên dịch trước tiêu đề cho tệp .h đó.

Bạn có thể đọc về nó ở đây: http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html

Vì vậy, đây là lý do bạn có thể thấy .h file được đưa trực tiếp đến GCC.

3

Được rồi, hãy hiểu sự khác biệt giữa mã hoạt động và mã thụ động.

Mã hoạt động là triển khai các hàm, thủ tục, phương pháp, tức là các đoạn mã cần được biên dịch thành mã máy thực thi. Chúng tôi lưu trữ nó trong các tệp .c và chắc chắn chúng tôi cần phải biên dịch nó.

Mã thụ động không tự thực thi, nhưng cần phải giải thích các mô-đun khác nhau cách liên lạc với nhau. Thông thường, các tệp .h chỉ chứa các nguyên mẫu (các tiêu đề hàm), các cấu trúc.

Một ngoại lệ là các macro, chính thức có thể chứa một phần hoạt động, nhưng bạn nên hiểu rằng chúng đang sử dụng ở giai đoạn đầu của quá trình xây dựng (tiền xử lý) với sự thay thế đơn giản. Tại các macro thời gian biên dịch đã được thay thế cho tệp .c của bạn.

Ngoại lệ khác là mẫu C++, cần được triển khai trong tệp .h. Nhưng đây là câu chuyện tương tự như các macro: chúng được thay thế ở giai đoạn đầu (instantiation) và chính thức, mỗi instantiation khác là một kiểu khác.

Tóm lại, tôi nghĩ, nếu các mô-đun được tạo đúng cách, chúng ta không bao giờ nên biên dịch các tệp tiêu đề.

1

Tôi nghĩ chúng ta cần tiền xử lý (có thể KHÔNG gọi là biên dịch) tệp đầu. Bởi vì từ sự hiểu biết của tôi, trong giai đoạn biên dịch, tệp đầu nên được bao gồm trong tệp c. Ví dụ, trong test.h chúng tôi có

typedef enum{ 
    a, 
    b, 
    c 
}test_t 

và trong test.c chúng tôi có

void foo() 
{ 
    test_t test; 
    ... 
} 

trong biên dịch, tôi nghĩ rằng trình biên dịch sẽ đặt mã trong tập tin đầu và tập tin c với nhau và mã trong tệp đầu sẽ được xử lý trước và thay thế mã trong tệp c. Trong khi đó, chúng ta nên xác định đường dẫn include trong makefile.

0

Trong một số hệ thống, các nỗ lực để tăng tốc độ lắp ráp các tệp '.c' được giải quyết hoàn toàn, gọi trước bao gồm các tệp bao gồm "biên dịch tệp tiêu đề". Tuy nhiên, nó là một kỹ thuật tối ưu hóa không cần thiết cho sự phát triển C thực tế.

Kỹ thuật như vậy về cơ bản đã tính toán các câu lệnh bao gồm và lưu giữ bộ nhớ cache của các phần tử được bao gồm. Thông thường, chuỗi công cụ C sẽ cắt và dán trong các tệp được đệ quy, rồi chuyển toàn bộ mục ra khỏi trình biên dịch. Với bộ đệm tiêu đề được biên dịch trước, chuỗi công cụ sẽ kiểm tra xem có bất kỳ đầu vào nào (định nghĩa, tiêu đề, v.v.) đã thay đổi hay không. Nếu không, sau đó nó sẽ cung cấp các đoạn văn bản tệp đã được làm phẳng tới trình biên dịch.

Các hệ thống như vậy được thiết kế để tăng tốc độ phát triển; tuy nhiên, nhiều hệ thống như vậy khá giòn. Khi các máy tính tăng tốc, và các kỹ thuật quản lý mã nguồn đã thay đổi, ít trình biên dịch trước tiêu đề thực sự được sử dụng trong dự án chung.

Cho đến khi bạn thực sự cần tối ưu hóa biên dịch, tôi khuyên bạn nên tránh việc biên dịch trước tiêu đề.

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