2012-01-16 11 views
10

Tôi có một chức năng static inline định nghĩa trong một tập tin H, và tại một thời điểm nào đó trong một file C, tôi gán một con trỏ đến chức năng, một cái gì đó như thế này:C: Con trỏ trỏ tới nội tuyến chức năng

foo.h :

static inline void frobnicate(void) { 
    // frobs something. 
} 

foo.c

#include "foo.h" 

void execute(void (*func)(void)) { 
    func(); 
} 

void blahBlahBlah(void) { 
    execute(frobnicate); 
} 

bar.c

#include "foo.h" 
// ... 
frobnicate(); 

Vì vậy, tôi nghĩ điều gì sẽ xảy ra ở đây là trình biên dịch sẽ chuyển nội dung cuộc gọi đến frobnicate từ bar.c, nhưng trong foo.c, nó sẽ thực sự phải tạo một hàm để triển khai frobnicate, để nó có thể hoạt động con trỏ đến nó.

Có ai có thể xác nhận nếu hiểu biết của tôi là chính xác không và sửa tôi bằng cách khác?

+2

* Bạn * có thể xác nhận bằng cách đọc mã được tạo. Tôi không nghĩ rằng có một cách cụ thể trong đó * này có * để làm việc. Tôi sẽ không ngạc nhiên nếu trình biên dịch đi "ai đó muốn địa chỉ này, vì vậy chúng ta không inline nó, sau đó". – unwind

+7

Hãy nhớ rằng 'inline' chỉ là _suggestion_ đối với trình biên dịch –

Trả lời

10

inline là một trong những từ định nghĩa sai của tiêu chuẩn C. Ý nghĩa chính của nó là có thể đặt định nghĩa của một hàm trong một tệp tiêu đề mà không phải đối phó với các vấn đề "nhiều định nghĩa" tại thời gian liên kết.

Cách chính thức trong C99 và C11 để thực hiện những gì bạn muốn đạt được là có định nghĩa inline trong tệp tiêu đề, không có static. Vì bạn cũng cần biểu tượng được phát ra, bạn cần phải thông báo cho trình biên dịch biết đơn vị biên dịch này nên là gì. Bạn có thể thực hiện việc tạo bản sao này bằng cách khai báo trong tệp .c đó trong đó bạn bỏ qua từ khóa inline.

Tự nhiên nhất bạn có thể sử dụng tệp .c nơi bạn thực sự cần biểu tượng.

+0

Nếu định nghĩa nội tuyến nằm trong tệp tiêu đề không có 'tĩnh', thì tôi sẽ không có nhiều định nghĩa cùng tên (hàm nội tuyến) khi tôi cố liên kết? – brianmearns

+0

Bạn sẽ gặp phải sự cố liên kết. Hoặc làm cho nó 'tĩnh nội tuyến', và nhiều định nghĩa rủi ro, hoặc từ bỏ nội tuyến.Bạn cũng có thể làm cho một wrapper, mà sẽ được trong một tập tin C và sẽ không được nội tuyến, và có một con trỏ đến nó (không có hiệu suất hit, bởi vì các chức năng thực sự sẽ được inlined vào wrapper). – ugoren

+0

@bmearns, với trình biên dịch tuân thủ C99, bạn sẽ không có vấn đề liên kết. Đây chính xác là ý nghĩa của từ khoá 'inline'. http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ –

7

Có, bạn đã đúng. Khi bạn đưa con trỏ đến hàm, trình biên dịch phải tạo một phiên bản "độc lập", nơi mã có thể được gọi là một hàm bình thường.

Lợi ích của việc nội tuyến một chức năng là mã gọi không cần phải được tạo và bất kỳ tối ưu hóa nào khác có thể được đưa vào để tích hợp cả chức năng người gọi và chức năng nội tuyến. Nhưng khi bạn cần thực hiện một cuộc gọi thông thường đến hàm (như khi bạn lấy địa chỉ để gọi nó sau này), những tối ưu hóa đó không thể thực hiện được nữa.

+2

Điều này có thể đúng đối với nhiều trình biên dịch, nhưng tôi không thể tưởng tượng được tại sao trình biên dịch lại được yêu cầu làm như vậy. Ví dụ của OP có thể được inlined khá dễ dàng ngay cả trong trường hợp con trỏ hàm. –

+0

'inline' là một khuyến nghị. Nếu trình biên dịch không thể nội tuyến, nó sẽ không, và nếu nó không thể, nó vẫn có thể quyết định không (và nó có thể inline ngay cả khi không có từ khoá 'inline'). Con trỏ chức năng thường ngăn chặn nội tuyến, mặc dù trong trường hợp này trình biên dịch có thể tìm ra rằng chúng không (hoặc nó có thể không bận tâm). – ugoren

+0

Có, trong trường hợp này, có thể nội tuyến hàm. Tôi cho rằng đây là một phiên bản đơn giản của vấn đề. Nhưng bạn đúng. – Governa