2016-03-10 19 views
8

Przypadkowo przyłapałem się na używaniu dwóch różnych stylów definicji wskaźników funkcji C w różnych miejscach i postanowiłem napisać program minimalny, aby przetestować te różnice.Czy te dwa style definicji wskaźnika funkcji C są różne?

Oba style których mowa, to:

int (comp (int)) 

i

int (*comp)(int) 

pisałem minimalny program, który używa obu tych stylów dla tego samego wskaźnika funkcji, jeden dla deklaracji z funkcja i jedna dla tej samej funkcji, aby zobaczyć, co miałby do powiedzenia kompilator.

Oświadczenie:

int a_or_b (int (*a_fn)(), int (b_fn()), int (*comp)(int)); 

Definicja:

int a_or_b (int (a_fn()), int (*b_fn)(), int (comp(int))) 
{ 
    int out = a_fn(); 
    if (comp (out)) 
     out = b_fn(); 
    return out; 
} 

Jak można (mam nadzieję) widać, dla pierwszego parametru w deklaracji użyłem stylu int (*a_fn)(), podczas gdy w definicji funkcji , Użyłem stylu int (a_fn()). Robię coś podobnego z następnymi dwoma argumentami.

I Przypuszcza się, że może to być niekompatybilne typów, tych stylów może być różnica pomiędzy odniesieniem przejazdu, i przechodzi przez wartość przydziału zmiennej, ale gdy opracowano program kompilator cicho i szczęśliwie zestawiane to. Brak błędów, brak ostrzeżeń, nic.

Jak widziałem wiele tutoriali opowiadających się za drugim stylem, podczas gdy ja osobiście preferuję pierwszy styl dla celów estetycznych, interesuje mnie różnica między tymi dwoma stylami i która jest zalecana.

Pełny przykład kod:

#include <stdio.h> 

int a(); 
int b(); 
int a_or_b (int (*a_fn)(), int (b_fn()), int (*comp)(int)); 

int a() 
{ 
    return 1; 
} 

int b() 
{ 
    return 2; 
} 

int comparison (int param) 
{ 
    return param; 
} 

int a_or_b (int (a_fn()), int (*b_fn)(), int (comp(int))) 
{ 
    int out = a_fn(); 
    if (comp (out)) 
     out = b_fn(); 
    return out; 
} 

int main (int argc, char **argv) 
{ 
    printf ("%i\n", a_or_b (a, b, comparison)); 
    return 0; 
} 
+2

Na liście parametrów funkcji "funkcje" przekształcają się w wskaźniki funkcji. ISO/IEC 9899: 2011 §6.7.6.3 Deklaratory funkcji (w tym prototypy) mówią: _¶8 Deklaracja parametru jako "funkcja zwracająca funkcję" "jest dostosowywana do" wskaźnika do funkcji zwracającego typu "" ... _ –

Odpowiedz

4

Na liście parametrów funkcji funkcje są konwertowane na wskaźniki funkcji. Norma C11, ISO/IEC 9899: 2011, §6.7.6.3 declarators funkcyjną (włącznie z prototypami) mówi:

¶8 deklaracja parametru jako „powracającego funkcji typu” koryguje się do wartości „wskaźnik na funkcję zwracającą typ” ...

Więc, jak napisano, wszystkie parametry są traktowane jako "wskaźnik do funkcji". Najlepiej jednak być konsekwentnym.

Zauważ, że funkcja nie może wrócić funkcję:

¶1 Funkcja declarator nie określi typ zwrotny, który jest rodzajem funkcji lub typ tablicy.

poza declarator funkcji (lista argument definicji funkcji lub deklaracji funkcji), oznaczenia są różne:

int (*a_fn)(); 
int (b_fn()); 

Pierwszy z nich deklaruje (definicja) zmienną o nazwie a_fn - wskaźnik do funkcji zwracającej int z nieokreśloną (ale nie variadyczną) listą argumentów.

Drugi z nich deklaruje istnienie funkcji o nazwie b_fn zwracającej int z nieokreślonej (ale nie o zmiennej liczbie argumentów) listy argumentów (i ma zbędny zestaw nawiasie; może to być napisane int b_fn(); i oznacza to samo).

+0

Ta odpowiedź wydaje się obejmować każdy przypadek. Dzięki! –

2

Zarówno int (comp (int)) i int (*comp)(int) odpowiadają stosowane jako parametry funkcyjne. Oznaczniki funkcji są przekształcane na wskaźniki w samą funkcję.

C11-§6.3.2.1:

Funkcja oznaczenie to wyrażenie jest typu funkcji. Z wyjątkiem argumentu operatora sizeof, operatora _Alignof, operatora jednoargumentowego &, oznaczenie funkcji z typem "typ zwracany przez funkcję" jest konwertowane na wyrażenie, które ma typ "wskaźnik zwracający typ funkcji" .

+0

Dziękuję za odpowiedź! Czy są przypadki, w których te dwa style zachowują się inaczej? –

+3

@MarcusHarrison Na najwyższym poziomie 'int (comp (int))' jest prototypem dla funkcji o nazwie 'comp', która pobiera i zwraca' int', podczas gdy 'int (* comp) (int)' jest wskaźnikiem -funkcjonować. –

Powiązane problemy