Các gcc documentation chứa sau:Các cuộc gọi đứng trước định nghĩa của hàm không thể được gạch chân?
Khi một chức năng vừa là nội tuyến và tĩnh, nếu tất cả các cuộc gọi đến các chức năng được tích hợp vào người gọi và địa chỉ của chức năng là không bao giờ được sử dụng, sau đó lắp ráp riêng của chức năng mã không bao giờ được tham chiếu . Trong trường hợp này, GCC không thực sự xuất mã assembly cho hàm, trừ khi bạn chỉ định tùy chọn -fkeep-inline-functions. Không thể tích hợp một số cuộc gọi vì nhiều lý do khác nhau (cụ thể, cuộc gọi đứng trước định nghĩa của hàm không thể được tích hợp và không thể gọi lại đệ quy trong định nghĩa ).
Điều đó luôn có vẻ vô lý đối với tôi - tại sao trình biên dịch hiện đại lại ngu ngốc? Sau một thử nghiệm nhanh, nó có vẻ không đúng sự thật.
Mã kiểm tra:
static inline int foo();
int bar() {
return foo();
}
int foo() {
return 42;
}
Kết quả với gcc-4.9.2 trên Linux chứa mã cho bar()
nhưng không ai cho foo()
. Bạn có thể thấy rằng foo()
đã được tích hợp:
bar:
.LFB0:
.cfi_startproc
movl $42, %eax
ret
.cfi_endproc
Nếu tôi biên dịch như C++ kết quả là như nhau, ngoại trừ tên mangling.
Trái với tài liệu, mặc dù foo()
được xác định sau khi cuộc gọi trong bar()
, foo()
đã được tích hợp hoàn toàn vào bar()
.
Tôi có hiểu nhầm tài liệu hoặc không chính xác không? Có lẽ nó đúng cho một số trường hợp phức tạp hơn?
Tôi không biết nếu có sự khác biệt về kỹ thuật giữa "tích hợp" và "nội tuyến" nhưng tôi nghi ngờ "tích hợp" đang được sử dụng để phân biệt với từ khóa inline
và nó chỉ đề cập đến chức năng nội tuyến (do đó tiêu đề).
Câu hỏi này được gắn thẻ là C và C++ vì phần này của tài liệu gcc liên quan đến "ngôn ngữ gia đình C" và tôi cho rằng câu trả lời giống nhau cho hai ngôn ngữ.
Câu đó đã có trong tài liệu gcc 3.0.4. Họ có thể tăng cường trình biên dịch mà không sửa đổi tài liệu. – AProgrammer
Vâng. Có vẻ như nó không tương ứng với những gì thực sự xảy ra. Mặc dù, tôi đã thử nó cũng trên 4.8.1 - hành vi tương tự. – SGrebenkin
Nó thậm chí trong tài liệu gcc 2.95.3. – Praxeolitic