int (*ptr)(char (*ch)[]);
Tuyên bố trên có nghĩa là gì? Điều đó có nghĩa làĐối số chấp nhận con trỏ hàm
ptr là con trỏ tới hàm có chấp nhận đối số là mảng con trỏ đến các ký tự trả về số nguyên không?
Cách đánh giá?
int (*ptr)(char (*ch)[]);
Tuyên bố trên có nghĩa là gì? Điều đó có nghĩa làĐối số chấp nhận con trỏ hàm
ptr là con trỏ tới hàm có chấp nhận đối số là mảng con trỏ đến các ký tự trả về số nguyên không?
Cách đánh giá?
Có quy tắc: http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html
Tóm lại, bạn nên bắt đầu từ định danh, sau đó phân tích mọi thứ, từ nhận dạng bên phải (nó có thể được ()
-chức năng hoặc []
mảng), sau đó phân tích mọi thứ, từ nhận dạng để Bên trái. Dấu ngoặc đơn thay đổi thứ tự này - bạn nên phân tích cú pháp mọi thứ trong ngoặc đơn bên trong đầu tiên và cứ như vậy, nó hoạt động giống như với phép tính số học.
Nói cách khác, có một trật tự ưu tiên (có thể được thay đổi bằng dấu ngoặc đơn), từ cao đến thấp:
1) ()
- chức năng và []
-mảng, từ trái bên phải;
2) *
- con trỏ, loại, loại modifier, từ phải sang trái.
dụ bạn
int (*ptr)(char (*ch)[])
Chúng tôi bắt đầu từ định danh
int (*ptr)(char (*ch)[]); // (1)ptr
|_|
1
Định danh ptr
là trong ngoặc đơn, vì vậy chúng tôi phân tích tất cả mọi thứ trong parenteses đầu tiên
(*ptr) // (1)ptr
|_|
1
Không có gì sang bên phải là, vì vậy chúng tôi phân tích ở phía bên trái
(*ptr) // (1)ptr is (2)a pointer
||_|
2 1
Chúng tôi hoàn thành trong ngoặc đơn, bây giờ chúng tôi phân tích ở bên phải của dấu ngoặc đơn
int (*ptr)(char (*ch)[]); // (1)ptr is (2)a pointer to (3)function
||_| |____________|
2 1 3
Cho đến nay chúng ta bỏ qua đối số chức năng và phân tích ở bên trái của dấu ngoặc đơn
int (*ptr)(char (*ch)[]); // (1)ptr is (2)a pointer to (3)function which returns (4)int
|_| ||_| |____________|
4 2 1 3
Giống như cách chúng tôi phân tích đối số của hàm (Tôi đã chèn một số khoảng trắng để căn chỉnh tốt hơn)
char (* ch)[ ] // (1)ch is (2)a pointer to (3)array of (4)chars
|___| | |_| |_|
4 2 1 3
Cuối cùng, ta có:
ptr là con trỏ đến chức năng trả về int và chấp nhận một con trỏ đến mảng các ký tự như là đối số
Nó hoạt động tốt trong GCC.
Có ptr
là con trỏ hàm. Nó là một con trỏ trỏ đến một hàm trả về một số nguyên và chấp nhận một con trỏ tới một mảng ký tự làm đối số.
Hãy xem xét các chức năng vui vẻ với nguyên mẫu sau,
int fun(char (*ptr)[]);
fun()
là một chức năng chấp nhận một con trỏ đến một mảng ký tự như là đối số.
và đoạn mã sau biên dịch mà không cần bất kỳ lỗi hoặc cảnh báo,
int (*ptr)(char (*ch)[]);
ptr=fun;
Câu hỏi được gắn thẻ C++. G + + không biên dịch được mã này. Xem: http://ideone.com/G7kJpr – jxh
ptr là con trỏ đến một chức năng chấp nhận một cuộc tranh cãi mà là một con trỏ đến một loạt các nhân vật, trở về số nguyên.
Như bạn đã viết, ptr
là một con trỏ đối với hàm trả về int
và lấy làm đối số con trỏ tới mảng char
.
Tuy nhiên, bạn không được phép có con trỏ tới mảng mà không bị ràng buộc trên mảng. Vì vậy, biến của bạn được chỉ định không chính xác và sẽ không biên dịch. Có vẻ như bạn muốn ptr
để có loại có thể chấp nhận con trỏ đến hàm có thể lấy bất kỳ mảng kích thước nào. Điều này đòi hỏi phải xây dựng mẫu. Đối với một luận cứ chức năng, nó sẽ có dạng:
template <unsigned N>
int foo (int (*ptr)(char (*)[N])) {
//...
}
Thông thường, cách để đơn giản hóa các loại như vậy là để sử dụng typedef
để đại diện cho những phần phức tạp, do đó biến bản thân trở thành một con trỏ đơn giản đối với một số loại. Điều này đặc biệt hữu ích khi cố gắng viết một hàm trả về một con trỏ hàm.
void x (char *s) {}
typedef void xtype (char *);
void (* y_hard())(char *) { return x; }
xtype * y_easy() { return x; }
Tuy nhiên, tính chất tham số của đối số hàm khiến khó đạt được hơn. Giả sử C++ 11, bạn có thể sử dụng cấu trúc sau (thanks to this answer):
template <unsigned N>
using ArrayArg = const char [N];
template <unsigned N>
using Function = int (ArrayArg<N> *);
template <unsigned N>
int foo (Function<N> *ptr) {
//...
}
Đây là một khu vực của C mà các nhà thiết kế có kinh khủng nặng sai! –
True! Rất khó để đánh giá các biểu thức như vậy .. – RDX
Đây là lỗi cú pháp. –