2010-04-09 19 views
6

Mówili to wyrażenie jest poprawne w C, a to oznacza to wywołanie funkcji:rozszyfrowania (* (void (*)() 0))()

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

Może ktoś dokładnie wyjaśnić, co to oznacza wyrażenie ?

Próbowałem to skompilować i byłem zaskoczony, że nie spowodował błędu.

+2

Dziwne, że nazywamy to ukrytą funkcją. –

+0

"To nie jest niezdefiniowane zachowanie ... to funkcja!". Nie, to niezdefiniowane zachowanie. –

Odpowiedz

18

Krok po kroku:

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 

Kod jest niezdefiniowane zachowanie, to będzie prawdopodobnie zawiesza się z jakimś nielegalnym dostępem/segfault.

+0

@Steve Jessop: Dzięki za odpowiedź na szczegóły – NguyenDat

+2

Właściwie ten kod będzie miał zachowanie specyficzne dla platformy, na której ją kompilujesz. Może być jasno określony dla niektórych platform, a nielegalny dla innych. Niedawno kupiłem mikrokontroler, a kiedy jest on aktywowany, wykonuje w pamięci kod zaczynający się od adresu 0. Ten kod przeskoczyłby na początek programu. – Ponkadoodle

+2

Dobrze, że mikrokontroler jest jednym z przypadków, co oznacza, że ​​tylko * prawdopodobnie * wywala - prawdopodobieństwo, że nguyendat używa platformy, na której nie będzie niska ;-) Kiedy mówię "niezdefiniowane zachowanie" oczywiście mam na myśli , jak zawsze, niezdefiniowana przez standard C. Poszczególne wdrożenia mogą zagwarantować, co zrobią w konkretnych przypadkach niezdefiniowanego zachowania. –

6

Tworzysz wskaźnik do funkcji, a następnie ją wywołujesz. Nie nazwałbym tego ukrytą cechą, ale nieokreślonym zachowaniem.

Zasadniczo to robisz, ale z adresem 0 zamiast:

void test() { } 

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

Jest to wskaźnik do funkcji w NULL.

void(*)() to definicja wskaźnika do funkcji, która nie przyjmuje argumentów, które niczego nie zwracają; można nazwać go:

typedef void(*my_func)(); 

następnie w Twojej przykład masz obsadę:

(my_func)0 daje wskaźnik funkcji do my_func, czyli funkcją biorąc nic i nic nie wraca.

Następnie usuwasz je za pomocą wiodącej gwiazdki (co jest niepotrzebne, afaik), a następnie wywołujesz ją.

Wywołujesz funkcję, która nie przyjmuje żadnych argumentów i nie zwraca niczego, co zdarza się przy zerowym adresie.

Jest to (zazwyczaj) niezdefiniowane zachowanie i natychmiast zawiesi się na wielu platformach. (To nie jest niezdefiniowane zachowanie jeśli umieścisz funkcję na adres zerowy, przynajmniej ja nie sądzę, że było).

2

Podziel na nawias.

Ostatnia () oznacza funkcję bez parametrów.

Linia (void(*)()) oznacza funkcję, która zwraca void.

Ostatnio trochę The (* na początku i 0) mówi kompilatorowi, że adres funkcji, aby zadzwonić do kłamstwa w miejscu kursora 0.

Więc w zasadzie, dzwonisz do cholery co leży u adres 0 bez parametrów. Zwykle nie jest to bardzo bezpieczne. :)

0

w środowisku wbudowanym może być sposobem wywołania procedury resetowania systemu.