2012-01-04 39 views
11

Tôi đã hai tập tin sau đây:Biên soạn nhiều file C trong một chương trình

file1.c

int main(){ 
    foo(); 
    return 0; 
} 

file2.c

void foo(){ 

} 

Tôi có thể biên dịch và liên kết hai tập tin với nhau để file1.c sẽ nhận ra các chức năng foo mà không cần thêm extern?

Đã cập nhật mẫu thử nghiệm.

tệp gcc1.c tệp2.c ném: cảnh báo: khai báo ngầm của hàm foo.

+1

'gcc file1.c file2.c', tôi cũng không biết quy tắc chính xác của C cho các cuộc gọi hàm khi không thấy nguyên mẫu nhưng bạn có thể phải thêm' int foo(); 'above' main' –

+0

@ Seth: hãy luôn luôn -bao gồm '-Wall' khi đưa ra các ví dụ gcc - nó giúp để có được noobs thành thói quen tốt. –

+0

Tôi đã cập nhật câu hỏi. Tôi làm điều đó với -Wall. – mary

Trả lời

4

Bạn không cần extern, nhưng tệp1.c phải xem tuyên bố rằng foo() tồn tại. Thông thường, khai báo này nằm trong một tệp tiêu đề.

Để thêm tuyên bố chuyển tiếp mà không sử dụng tệp tiêu đề, chỉ cần sửa đổi tệp1.c để:

int foo(); // add this declaration 

int main(){ 
    foo(); 
    return 0; 
} 
+0

Tôi có thể làm điều đó mà không có bất kỳ tập tin tiêu đề chỉ bằng cách biên dịch hai với nhau? – mary

+0

Bạn vẫn cần khai báo chuyển tiếp 'foo()', bạn có thể thực hiện trong file1.c nếu muốn. – chrisaycock

+0

@mary có, tệp tiêu đề là dành cho trình biên dịch nhưng điều này được thực hiện bởi trình liên kết –

5

Bạn có thể, nhưng bạn không nên.

Sử dụng một tập tin header, file2.h:

// file2.h 

void foo(); // prototype for function foo() 

Sau đó thêm:

#include "file2.h" 

trong file1.c

Để biên dịch:

$ gcc -Wall file1.c file2.c -o foo 

Là một quy tắc chung nó tốt hơn (mạnh mẽ hơn) đối với chúng tôi e tệp tiêu đề để xác định giao diện của mỗi mô hình mô-đun thay vì ad hoc trong các mô-đun phụ thuộc. Điều này đôi khi được gọi là nguyên tắc SPOT (Single Point Of Truth).

+3

@Anonymous down-cử tri: xin vui lòng làm rõ phản đối của bạn? –

+0

Bạn không cần 'extern' để gọi hàm, bạn chỉ cần mẫu thử nghiệm, như' int foo(); 'trong tiêu đề và nội dung trong' file2.c' –

+0

@Seth: true - bạn không * cần * nó, nhưng không có gì sai khi làm cho nó rõ ràng. –

20

Cách đúng là như sau:

file1.c

#include <stdio.h> 
#include "file2.h" 

int main(void){ 
    printf("%s:%s:%d \n", __FILE__, __FUNCTION__, __LINE__); 
    foo(); 
    return 0; 
} 

file2.h

void foo(void); 

file2.c

#include <stdio.h> 
#include "file2.h" 

void foo(void) { 
    printf("%s:%s:%d \n", __FILE__, __func__, __LINE__); 
    return; 
} 

output

$ 
$ gcc file1.c file2.c -o file -Wall 
$ 
$ ./file 
file1.c:main:6 
file2.c:foo:6 
$ 
+0

Định danh được xác định trước C99 là '__func__'. Ưu tiên điều này cho gcc cụ thể '__FUNCTION__'. – pmg

+1

Tôi không nghĩ rằng đó là thực hành tốt để vượt qua tiêu đề để trình biên dịch như thế - nếu nó là cần thiết, các bộ tiền xử lý sẽ mang lại cho nó in –

+0

@TimothyJones lời xin lỗi của tôi. Đó là một điểm tốt. Cảm ơn bạn đã kiểm tra câu trả lời! .. Tôi đã sửa nó ngay bây giờ! –

2

Nó xấu xí, nhưng sử dụng gcc, bạn có thể:

gcc -include file2.c file1.c 

-include là một lá cờ để tiền xử lý sẽ bao gồm các nội dung của file2.c ở đầu rất của file1.c. Có nói rằng, đó là một sự lựa chọn nghèo, và phá vỡ cho tất cả, nhưng đơn giản nhất của chương trình.

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