Được rồi, vì vậy sau khi đọc qua VivienG's link, tôi nghĩ rằng tôi đã hiểu được lý do chính xác đằng sau thông báo lỗi này. Đó là khó hiểu và gây hiểu lầm (ít nhất là với tôi, nó không nên xảy ra nếu bạn đã có chỉ là một đơn vị dịch thuật), tuy nhiên nó có thể giải thích:
Giả sử các trình biên dịch không muốn thực sự inline mã, nó phải biết nơi để đặt chức năng đó, đặc biệt là khi nó được sử dụng trong nhiều đơn vị dịch thuật.
Cách tiếp cận cổ điển là tạo nhiều bản sao, một bản sao cho mỗi đơn vị dịch (hoặc ít nhất là đối với các đơn vị dịch mà nó được sử dụng).
Điều này có thể gây ra sự cố, ví dụ: khi cố gắng thực hiện một số phép so sánh con trỏ hàm (vẫn để nguyên câu hỏi tại sao bạn lại làm điều đó).
Để chống lại điều này (và các vấn đề khác mà tôi có thể không liệt kê ở đây), họ đã suy nghĩ của một số thực sự khá gọn gàng (mặc dù - như đã đề cập - theo ý kiến của tôi gây hiểu lầm) giải pháp:
Bạn khai báo hàm như inline
theo cách bạn biết, nhưng đồng thời bạn cho trình biên dịch biết nơi đặt phiên bản không nội tuyến với từ khóa extern
.
Vì vậy, trong ví dụ của bạn, bạn muốn giữ cho chức năng của bạn như nó vốn có và đặt nó trong một tập tin tiêu đề (vì vậy nó được biết đến nơi nó sẽ được sử dụng):
inline int foo(void)
{
return 10 + 3;
}
Bên cạnh đó, để nói với trình biên dịch nơi đặt phiên bản không được nội tuyến, bạn sẽ phải thêm một bản khai báo "chuyển tiếp" khác vào một đơn vị dịch:
extern inline int foo(void);
Vì vậy, toàn bộ khái niệm cơ bản được đảo ngược khi so sánh với các chức năng cổ điển: trong tiêu đề và sau đó khai báo ngắn chỉ trong một tệp.
Như đã đề cập, khi sử dụng tham số -O3
, tất cả mã được đánh dấu bằng inline
thực sự được gạch chân, điều này sẽ không gây ra sự cố.
https://gcc.gnu.org/onlinedocs/gcc/Inline.html – Ashalynd
@Ashalynd câu trả lời có thể là ở đâu đó, nhưng đó là gì? – harold
Tôi tự hỏi liệu sự cần thiết cho 'extern' là GCC cụ thể hoặc một phần của một số tiêu chuẩn C. 'inline' được thêm vào C99 tôi tin, nhưng tôi không biết nó ảnh hưởng đến liên kết như thế nào. –