2011-11-05 39 views
25

Tôi tin rằng một hàm tĩnh trong một tệp nguồn không thể được gọi trực tiếp từ bên ngoài tệp. Tuy nhiên, nếu tôi bằng cách nào đó quản lý để có được một con trỏ đến chức năng này vào một tập tin khác, sau đó tôi có thể gọi chức năng này từ tập tin đó. Nếu có, có bất kỳ kịch bản nào khi chúng tôi muốn thực hiện tuyến đường này so với việc đơn giản là làm cho hàm không tĩnh?Có thể gọi hàm tĩnh thông qua một con trỏ hàm trong C?

+1

Tôi tự hỏi hành vi là gì nếu bạn kết hợp điều này với từ khóa 'inline' và/hoặc chỉ thị trình biên dịch độc quyền sẽ luôn luôn nội tuyến một hàm. – mpontillo

+0

@mpontillo Tôi tin rằng ngay cả khi hàm được đánh dấu là 'inline' nhưng địa chỉ được lấy trong một con trỏ hàm, trình biên dịch sẽ sinh ra phần tử nhị phân, trong khi cũng in nó vào các hàm khác trong cùng một mô-đun. –

Trả lời

28

Có, bạn có thể xuất các hàm tĩnh bằng cách đưa ra các con trỏ tới chúng. Đây là phương tiện phổ biến để triển khai Factory pattern trong C, nơi bạn có thể ẩn các triển khai của toàn bộ các hàm từ các mô-đun sử dụng chúng và có FuncPtr_t GetFunction(enum whichFunctionIWant) đưa chúng ra cho người tiêu dùng. Đó là số lượng việc triển khai dynamic linking hoạt động.

3

Có, chức năng không tĩnh trong tệp của bạn có thể trả về con trỏ tới hàm tĩnh ở bất kỳ nơi nào bạn muốn.

9

Tuy nhiên, nếu tôi bằng cách nào đó quản lý để lấy con trỏ đến hàm này vào một tệp khác, thì tôi có thể gọi hàm này từ tệp đó.

Có, điều đó hoàn toàn có thể. Hàm này không hiển thị với trình liên kết, nhưng nó có trong tệp thực thi. Bạn luôn có thể chuyển đến địa chỉ của nó.

Tôi không chắc chắn về các trường hợp. Có thể bạn muốn người khác chỉ gọi hàm của bạn sau họ gọi một số chức năng khác (không tĩnh tất nhiên). Vì vậy, bạn có họ có được nó, và sau đó họ có thể gọi nó.

3

Có, bạn có thể. Nếu bạn phải gọi một hàm mong đợi một con trỏ tới một hàm như một cuộc gọi lại, bạn có thể sử dụng tĩnh để biểu tượng hàm không gây ô nhiễm không gian tên chung và không gây xung đột liên kết. Ví dụ được sử dụng nhiều nhất có lẽ là qsort:

struct Data { ... }; 

static int compareData(const void* a, const void* b) { /* cast to Data and compare */ } 

... 
qsort(array, count, sizeof(Data), &compareData); 
4

Như đã đề cập, bạn có thể làm điều đó. Một ví dụ về lý do tại sao bạn có thể muốn cho một số loại "trình điều khiển". Bạn có thể trả về một cấu trúc chứa các hàm mở, đóng, đọc và viết mà không cần phải thực hiện các chức năng thực sự có thể truy cập công khai.

0

Có bạn có thể, bạn có thể luôn luôn thử nó cho chính mình và tìm hiểu:

file1.c

#include <stdio.h> 

void call_hello(void (*fptr)(void)); 

static void hello(void) { 
    puts("hello"); 
} 

int main(void) 
{ 
    void (*fptr)(void) = hello; 

    call_hello(fptr); 

    return 0; 
} 

file2.c

void call_hello(void (*fptr)(void)) 
{ 
    fptr(); 
} 
+8

Đó thường không phải là một cách tiếp cận tốt trong C. "Nó hoạt động" và "nó an toàn, sẽ làm việc ở khắp mọi nơi, và không dựa vào hành vi không xác định" thường là những điều rất khác nhau. –

2

Nó thường là hữu ích để xác định một hàm tĩnh nhỏ như một hàm công nhân cho một số hàm khác. Hãy xem ví dụ qsort tiêu chuẩn cho một ví dụ: nó mong đợi một hàm so sánh và thường là tốt hơn để làm cho hàm so sánh đó tĩnh (ví dụ: vì nó không hữu ích ở nơi khác và vì qsort muốn nó có chữ ký không đáng kể).

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