2010-04-09 52 views
6

Họ nói biểu hiện này là hợp lệ trong C, và rằng nó có nghĩa là gọi một hàm:giải mã (* (void (*)()) 0)()

(*(void(*)())0)(); 

Ai đó có thể giải thích rõ ràng điều này có nghĩa là biểu hiện ?

Tôi đã cố gắng biên dịch điều này và ngạc nhiên vì nó không dẫn đến lỗi.

+2

Lạ khi gọi đây là tính năng ẩn. –

+0

"Nó không phải là hành vi không xác định ... đó là một tính năng!". Không, đó là hành vi không xác định. –

Trả lời

18

Từng bước:

void(*)()  // a pointer-to-function type, taking unspecified parameters 
        // and returning nothing. 
    (void(*)())0  // a null pointer of that pointer-to-function type 
(*(void(*)())0)  // dereference that pointer 
(*(void(*)())0)(); // and call it with no parameters 

Mã này đã không xác định hành vi, nó sẽ có thể sụp đổ với một số loại truy cập/segfault bất hợp pháp.

+0

@Steve Jessop: Cảm ơn bạn đã trả lời chi tiết – NguyenDat

+2

Thực ra mã đó sẽ có hành vi cụ thể cho nền tảng mà bạn đang biên dịch nó. Nó có thể được xác định rõ ràng cho một số nền tảng, và bất hợp pháp trên những nền tảng khác. Gần đây tôi đã mua một bộ điều khiển vi mô và khi nó được kích hoạt, nó thực hiện mã bắt đầu tại địa chỉ 0 trong bộ nhớ. Vì vậy, mã đó sẽ nhảy đến đầu chương trình. – Ponkadoodle

+2

Phải, bộ điều khiển vi mô đó là một trong những trường hợp có nghĩa là nó chỉ * có thể * bị treo - xác suất mà nguyendat đang sử dụng nền tảng không thấp ;-) Khi tôi nói "hành vi không xác định" , như mọi khi, không xác định theo tiêu chuẩn C. Triển khai cụ thể có thể đảm bảo những gì họ sẽ làm trong các trường hợp cụ thể của hành vi không xác định. –

6

Bạn đang tạo một con trỏ tới một hàm và sau đó gọi nó. Tôi sẽ không gọi nó là một tính năng ẩn nhưng hành vi không xác định.

Về cơ bản bạn đang làm điều này nhưng với địa chỉ 0 thay vì:

void test() { } 

void(*pfn)() = test; 
(*pfn)(); 
3

Đó là một con trỏ tới một hàm tại NULL.

void(*)() là định nghĩa của con trỏ trỏ đến hàm không tham gia bất kỳ điều gì; bạn có thể đặt tên cho nó:

typedef void(*my_func)(); 

sau đó trong ví dụ của bạn, bạn đã có một dàn diễn viên:

(my_func)0 mang lại một con trỏ hàm để một my_func, có nghĩa là, một chức năng chụp gì và trở về không có gì.

Sau đó, bạn coi đó là dấu sao đầu tiên (không cần thiết, afaik) và sau đó bạn gọi nó.

Vì vậy, bạn đang gọi một hàm không có đối số và không trả lại điều gì xảy ra để sống ở địa chỉ 0.

Hành vi này (thường là) không xác định và sẽ gặp sự cố ngay lập tức trên nhiều nền tảng. (Nó không phải là hành vi không xác định nếu bạn đặt một chức năng tại địa chỉ không, ít nhất tôi sẽ không nghĩ nó là gì.)

2

Chia nhỏ mỗi dấu ngoặc đơn.

Cuối cùng () biểu thị một hàm không có tham số.

Dòng (void(*)()) có nghĩa là hàm trả về void.

Các chút qua, (* ngay từ đầu và 0) đang nói với trình biên dịch rằng địa chỉ của hàm để gọi những lời dối trá tại vị trí con trỏ 0.

Vì vậy, về cơ bản, bạn đang gọi bất cứ quái nằm ở địa chỉ 0 không có tham số. Không thường rất an toàn. :)

0

trong môi trường được nhúng, có thể là cách gọi cho thường trình đặt lại hệ thống.

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