Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Deklaracja funkcji poprzedza definicję funkcji i określa nazwę, typ zwracany, klasę magazynu i inne atrybuty funkcji. Aby być prototypem, deklaracja funkcji musi również ustanowić typy i identyfikatory argumentów funkcji.
Składnia
declaration
:
declaration-specifiers
attribute-seq
opt opt opt init-declarator-list
;
/* attribute-seq
opcja jest specyficzna dla firmy Microsoft */
declaration-specifiers
:
storage-class-specifier
declaration-specifiers
Zdecydować
type-specifier
declaration-specifiers
Zdecydować
type-qualifier
declaration-specifiers
Zdecydować
init-declarator-list
:
init-declarator
init-declarator-list
,
init-declarator
init-declarator
:
declarator
declarator
=
initializer
declarator
:
pointer
Zdecydować direct-declarator
direct-declarator
: /* Deklarator funkcji */
direct-declarator
(
parameter-type-list
)
/* Deklarator w nowym stylu */
direct-declarator
(
identifier-list
opt )
/* Deklarator w stylu przestarzałym */
Prototyp ma taką samą formę jak definicja funkcji, z tą różnicą, że jest on zakończony średnikiem bezpośrednio po nawiasie zamykającym i dlatego nie ma treści. W obu przypadkach zwracany typ musi być zgodny z typem zwrotnym określonym w definicji funkcji.
Prototypy funkcji mają następujące ważne zastosowania:
Ustanawiają typ zwracany dla funkcji, które zwracają typy inne niż
int
. Chociaż funkcje zwracająceint
wartości nie wymagają prototypów, zalecane są prototypy.Bez kompletnych prototypów są wykonywane konwersje standardowe, ale nie podjęto próby sprawdzenia typu lub liczby argumentów z liczbą parametrów.
Prototypy są używane do inicjowania wskaźników do funkcji przed zdefiniowanie tych funkcji.
Lista parametrów służy do sprawdzania, czy argumenty w wywołaniu funkcji są zgodne z parametrami w definicji funkcji.
Przekonwertowany typ każdego parametru określa interpretację argumentów, które wywołanie funkcji umieszcza na stosie. Niezgodność typów między argumentem a parametrem może spowodować błędną interpretację argumentów na stosie. Na przykład na komputerze 16-bitowym, jeśli wskaźnik 16-bitowy jest przekazywany jako argument, następnie zadeklarowany jako long
parametr, pierwsze 32 bity na stosie są interpretowane jako long
parametr. Ten błąd powoduje problemy nie tylko z parametrem long
, ale ze wszystkimi kolejnymi parametrami. Błędy tego typu można wykryć, deklarując kompletne prototypy funkcji dla wszystkich funkcji.
Prototyp ustanawia atrybuty funkcji. Następnie wywołania funkcji poprzedzające definicję funkcji (lub występujące w innych plikach źródłowych) można sprawdzić pod kątem niezgodności typu argumentu i zwracanego typu. Jeśli na przykład określisz static
specyfikator klasy magazynu w prototypie, musisz również określić klasę static
magazynu w definicji funkcji.
Pełne deklaracje parametrów (int a
) mogą być mieszane z deklaratorami abstrakcyjnymi (int
) w tej samej deklaracji. Na przykład następująca deklaracja jest legalna:
int add( int a, int );
Prototyp może zawierać zarówno typ, jak i identyfikator dla każdego wyrażenia przekazanego jako argument. Jednak takie identyfikatory są w zakresie tylko do końca deklaracji. Prototyp może również odzwierciedlać fakt, że liczba argumentów jest zmienna lub że nie są przekazywane żadne argumenty. Bez takiej listy niezgodność może nie zostać ujawniona, więc kompilator nie może wygenerować komunikatów diagnostycznych dotyczących nich. Aby uzyskać więcej informacji na temat sprawdzania typów, zobacz Argumenty.
Zakres prototypu w kompilatorze języka Microsoft C jest teraz zgodny ze standardem ANSI podczas kompilowania za pomocą opcji kompilatora /Za
. Jeśli zadeklarujesz struct
tag lub union
w ramach prototypu, tag zostanie wprowadzony w tym zakresie, a nie w zakresie globalnym. Na przykład podczas kompilowania z funkcją zgodności ANSI /Za
nigdy nie można wywołać tej funkcji bez wystąpienia błędu niezgodności typu:
void func1( struct S * );
Aby poprawić kod, zdefiniuj struct
union
lub w zakresie globalnym przed prototypem funkcji:
struct S;
void func1( struct S * );
W obszarze /Ze
tag jest nadal wprowadzany w zakresie globalnym.