Nhiều năm sau, tôi phát hiện ra câu hỏi này. Sau khi đọc mọi câu trả lời và bình luận, tôi nghĩ rằng tôi có thể làm rõ một vài chi tiết ... Điều này có thể hữu ích cho những người đến đây thông qua tìm kiếm của Google.
Câu hỏi cụ thể là về việc sử dụng các hàm "extern", vì vậy tôi sẽ bỏ qua việc sử dụng "extern" với các biến toàn cục.
Hãy xác định 3 nguyên mẫu hàm:
//--------------------------------------
//Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
int function_3(void);
Tệp tiêu đề có thể được sử dụng bởi mã nguồn chính như sau:
//--------------------------------------
//Filename: "my_project.C"
#include "my_project.H"
void main(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 1234;
Để biên dịch và liên kết, chúng ta phải định nghĩa "function_2" trong cùng một tệp mã nguồn nơi chúng ta gọi hàm đó. Hai hàm khác có thể được định nghĩa trong mã nguồn khác nhau " .C" hoặc chúng có thể nằm trong bất kỳ tệp nhị phân nào ( .OBJ, * .LIB, * .DLL) mà chúng tôi không có mã nguồn.
Hãy thêm lại tiêu đề "my_project.H" vào một tệp "* .C" khác để hiểu rõ hơn về sự khác biệt. Trong cùng một dự án, chúng tôi thêm tệp sau:
//--------------------------------------
//Filename: "my_big_project_splitted.C"
#include "my_project.H"
void old_main_test(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 5678;
int function_1(void) return 12;
int function_3(void) return 34;
Các tính năng quan trọng cần chú ý:
Khi một hàm được định nghĩa là "tĩnh" trong tệp tiêu đề, trình biên dịch / liên kết phải tìm một phiên bản của hàm có tên đó trong mỗi mô-đun sử dụng tệp bao gồm tệp đó.
Một chức năng là một phần của thư viện C chỉ có thể được thay thế trong một mô-đun bằng cách xác định lại một nguyên mẫu chỉ có "tĩnh" trong mô-đun đó. Ví dụ: thay thế bất kỳ cuộc gọi nào đến "malloc" và "miễn phí" để thêm tính năng phát hiện rò rỉ bộ nhớ.
Trình xác định "extern" không thực sự cần thiết cho các chức năng. Khi không tìm thấy "tĩnh", một hàm luôn được coi là "extern".
Tuy nhiên, "extern" không phải là mặc định cho các biến. Thông thường, bất kỳ tệp tiêu đề nào xác định các biến sẽ hiển thị trên nhiều mô-đun cần sử dụng "extern". Ngoại lệ duy nhất sẽ là nếu một tệp tiêu đề được đảm bảo được bao gồm từ một và chỉ một mô-đun.
Nhiều người quản lý dự án sau đó sẽ yêu cầu biến đó được đặt ở đầu mô-đun, không nằm trong bất kỳ tệp tiêu đề nào. Một số dự án lớn, chẳng hạn như trình giả lập trò chơi video "Mame" thậm chí yêu cầu biến đó chỉ xuất hiện phía trên hàm đầu tiên sử dụng chúng.