2010-07-23 36 views
16

Trong phần 7.1.1 của cuốn sách "The C++ Programming Language" các quốc gia tác giả:Các hàm nội tuyến có địa chỉ không?

"chức năng inline vẫn có một địa chỉ duy nhất và do đó, làm các biến tĩnh của một hàm nội tuyến"

Tôi đang bối rối . Nếu tôi có một hàm inline thì nó không thể có địa chỉ. Điều này cũng xảy ra trong C?

+1

Tôi nghĩ câu đó cần thêm ngữ cảnh. "hàm inline vẫn có một biến duy nhất" không có ý nghĩa. Tại sao bạn không nghĩ rằng một hàm nội tuyến có thể có một địa chỉ? –

+0

Ấn bản nào? Tôi đang xem ấn bản thứ ba, và không thể nhìn thấy nó nói ở đâu. – Clifford

+2

Trích dẫn chính xác từ sách - "Đặc biệt, một hàm nội tuyến vẫn có một địa chỉ duy nhất và do đó làm các biến tĩnh của một hàm nội tuyến". Đây là điều cuối cùng trong phần 7.1.1 - đoạn trước bắt đầu với "Trình định danh nội tuyến là một gợi ý * cho trình biên dịch" (nhấn mạnh của tôi). Các biến tĩnh được đề cập trong phần 7.1.2 – Steve314

Trả lời

34

Thuộc tính inline chỉ là một gợi ý cho trình biên dịch là nó nên cố gắng nội tuyến chức năng của bạn. Nó vẫn có thể lấy địa chỉ của hàm, và trong trường hợp đó trình biên dịch cũng sẽ cần phát ra một phiên bản không nội tuyến.

Ví dụ:

#include <stdio.h> 

inline void f() { 
    printf("hello\n"); 
} 

int main() { 
    f(); 
    void (*g)() = f; 
    g(); 
} 

Mã in trên hello hai lần.

trình biên dịch của tôi gcc (với -O) phát ra mã một cái gì đó như thế này:

_main: 
     pushl %ebp 
     movl %esp, %ebp 
     pushl %ebx 
     subl $20, %esp 
     call ___i686.get_pc_thunk.bx 
"L00000000002$pb": 
     leal LC0-"L00000000002$pb"(%ebx), %eax 
     movl %eax, (%esp) 
     call L_puts$stub  ; inlined call to f() 
     call L__Z1fv$stub  ; function pointer call to f() (g is optimised away) 
     movl $0, %eax 
     addl $20, %esp 
     popl %ebx 
     popl %ebp 
     ret 

Như bạn có thể thấy, có đầu tiên là một cuộc gọi đến puts() và sau đó một cuộc gọi đến L__Z1fv() (đó là tên đọc sai của f()).

+1

+1. Câu trả lời rất hay. – ereOn

3

Việc mở rộng nội tuyến của hàm không có địa chỉ, nhưng nếu hàm đó có biến tĩnh, biến sẽ có địa chỉ. Biến tĩnh về cơ bản chỉ là biến toàn cục có tên chỉ hiển thị cục bộ (tức là, trong phạm vi được xác định). Các biến khác trong một hàm nội tuyến có thể được cấp phát trên ngăn xếp (như chúng sẽ là nếu nó không được mở rộng nội tuyến) hoặc chúng có thể chỉ sống trong các thanh ghi máy. Phần quan trọng là chúng vẫn là các biến riêng biệt và phải hoạt động giống như hàm chưa được mở rộng nội tuyến (không giống như các macro, nơi cần phải cẩn thận để ngăn không cho nhiều đánh giá gây ra vấn đề).

5

Chức năng nội tuyến có địa chỉ nếu bạn cần. Tiêu chuẩn chỉ cho biết:

Một hàm nội tuyến có liên kết bên ngoài sẽ có cùng địa chỉ trong tất cả các đơn vị dịch.

+0

Đó có phải là hiện thân hoặc liên quan đến quy tắc * "như thể" * không? – jww

0

Chúng có thể được gạch chân tại các trang web cuộc gọi nhất định nhưng chúng vẫn tồn tại như chức năng bình thường trong không gian địa chỉ.

0

Tôi nghĩ bạn đang bối rối vị trí của mã đối tượng hàm nội tuyến, với hàm ý của nội tuyến. Thông thường chúng ta hình dung các chức năng nội tuyến như được đặt trong hàm gọi ở mức mã nguồn. Điều mà cuốn sách đang nói là các tên biến, bao gồm cả việc sử dụng các hàm tĩnh trong các hàm inline, được xử lý giống như khi hàm thực tế là hàm độc lập, điển hình của bạn.

Ngoài ra, việc xử lý các chức năng với từ khóa nội tuyến không đảm bảo rằng chúng sẽ được inline và trong trường hợp chúng không thể (chẳng hạn như khi yêu cầu địa chỉ), phiên bản không được nội tuyến sẽ được tạo.

5

Không có mâu thuẫn. Trong các phần có chức năng nội tuyến, mã của nó có thể được gạch chân. Trong các phần mà bạn sử dụng một con trỏ để hoạt động, một phiên bản không trực tuyến có thể được tạo để có một địa chỉ.

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