2017-08-15 17 views
8

Tôi đang cố gắng để giải mã tuyên bố này từ sqlite3.cLàm cách nào để diễn giải tuyên bố này dường như là khai báo hàm, nhưng không phù hợp với khuôn mẫu thông thường?

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); 

Nó có vẻ như nó được định nghĩa một hàm vì sau đó có này

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ 
    return pVfs->xDlSym(pVfs, pHdle, zSym); 
} 

và sau đó những gì xuất hiện được cuộc gọi đến chức năng

xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); 

xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); 

Nhưng tôi không thể hiểu được tuyên bố. Tôi đã nêu bật những gì tôi không thể hiểu

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); 
        ^             ^^^^^^^ 

Tôi đang tự hỏi lý do tại sao việc kê khai không giống như vậy

SQLITE_PRIVATE void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *); 

Tôi hy vọng rằng có cũng có thể là một câu hỏi tương tự đã hỏi nhưng tìm kiếm thuật ngữ như (, )void không thực sự đến bất kỳ đâu. Vì vậy, nếu đây là một bản dupe, tôi sẽ rất vui vì nó được đóng lại như vậy.

Trả lời

7

Đây là tuyên bố hàm trả về một con trỏ hàm. Kiểu trả về là void (*)(void) (SQLITE_PRIVATE mở rộng thành static và không phải là một phần của kiểu trả về, cho mỗi nhận xét), nhưng tên hàm (và tham số) phải xuất hiện bên trong phần (*).

Chức năng và mảng là hai danh mục loại C yêu cầu thực hiện phân tích. Bạn có thể nghĩ về các loại mảng và các loại chức năng như "trang trí" định danh mà chúng mô tả. Nếu bạn viết int foo, bạn đang nói rằng ký hiệu "foo" có kiểu số nguyên. Nếu bạn viết int foo(double), bạn đang nói rằng biểu tượng foo(double) có một loại số nguyên. foo(double) phải gắn kết với nhau, vì vậy bất kỳ trang trí thêm nào cũng phải quấn toàn bộ thứ như thể nó là một tên duy nhất.

Vấn đề là minh họa tốt nhất bằng cách trộn các loại mảng và các loại chức năng, mặc dù loại cuối có thể không hợp pháp tại C. (Đó là nói lên rất nhiều về cách lố bịch cú pháp là.) Ví dụ:

int foo[5](double) 

sẽ là một mảng (foo[5]) chức năng (int ... (double)). Mặt khác:

int foo(double)[5] 

là một chức năng (foo(double)) và trả về một mảng (int ... [5]).

Tài nguyên bên ngoài cdecl.org có thể giúp bạn hiểu rõ loại khai báo này. Tuy nhiên, bạn cần phải thay thế tên cấu trúc bằng các loại tiêu chuẩn (hoặc viết các loại cấu trúc là struct sqlite_vfs thay vì chỉ sqlite_vfs) để biết tên khai báo của bạn.

+0

Cảm ơn, tôi đã cố gắng cdecl.org, nhưng không thể có được nó để cho tôi bất cứ điều gì khác hơn là "lỗi cú pháp". Tôi có thể thấy bây giờ đó là vì nó không nhận ra 'sqlite3_vfs'. Nếu tôi chỉ thay thế 'sqlite3_vfs' bằng' int' thì tôi sẽ có câu trả lời. –

+0

Và điều khác khiến tôi hiểu rằng tôi cho rằng mặc dù 'sqlite3OsDlSym' trả về" con trỏ tới hàm (void) trả về void ", con trỏ hàm thực tế trả về có nguyên mẫu khác nhau, do đó' 'sqlite3_loadext_entry)' cast. –

+0

Tùy thuộc vào những gì 'SQLITE_PRIVATE' thực sự là, nó có thể áp dụng cho hàm được khai báo thay vì loại trả về (ví dụ: nếu đó là macro cho' static') –

2

khai này

SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); 

là một lời tuyên bố của một hàm có kiểu trả về là con trỏ hàm của các loại

void (*)(void) 

Việc kê khai có thể được đơn giản hóa bằng cách giới thiệu một typedef. Ví dụ:

typedef void (*FP)(void); 

SQLITE_PRIVATE FP sqlite3OsDlSym(sqlite3_vfs *, void *, const char *); 

Đây là chương trình minh họa sử dụng hàm tương tự trả về con trỏ đến hàm khác.

#include <stdio.h> 

typedef void (*FP)(void); 

void h(void) 
{ 
    puts("Hello World"); 
} 

FP f(void); 
void (*f(void))(void) 
{ 
    return h; 
} 

int main(void) 
{ 
    f()(); 

    return 0; 
} 

đầu ra của nó là

Hello World 

Lúc đầu chức năng f được khai báo sử dụng một typedef và sau đó nếu không có sự typedef

FP f(void); 
void (*f(void))(void) 
{ 
    return h; 
} 
Các vấn đề liên quan