2015-02-06 15 views
9

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ữ.

+5

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

+0

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

+3

Nó thậm chí trong tài liệu gcc 2.95.3. – Praxeolitic

Trả lời

7

Gcc được sử dụng để biên dịch và tối ưu hóa một hàm tại một thời điểm, ngay khi chúng được phân tích cú pháp, trước khi phân tích cú pháp tiếp theo. IIRC, nó chỉ nằm trong khung thời gian 4.X mà họ đã giới thiệu tùy chọn -funit-at-a-time đã trì hoãn việc tối ưu hóa sau khi đã đọc toàn bộ đơn vị biên dịch và sau đó họ đợi một số bản phát hành để bật nó theo mặc định.

Khả năng của nội tuyến được xác định sau khi cuộc gọi có thể được giới thiệu như một phần của tác phẩm -funit-at-a-time và tài liệu nội tuyến (đề cập đến cuộc gọi trước định nghĩa ngày trở lại ít nhất là 2,95) chưa được cập nhật.

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