Function Prototypes

  • 11/04/2016
  • 3 minuty na przeczytanie
    • c
    • v
    • . n
    • M
    • g
    • +1

Deklaracja funkcji poprzedza definicję funkcji i określa jej nazwę, typ zwracany, klasę przechowywania i inne atrybuty funkcji. Aby być prototypem, deklaracja funkcji musi również określać typy i identyfikatory dla argumentów funkcji.

Syntax

deklaracja:
declaration-specifiers attribute-seqopt init-declarator-listopt ;

/* attribute-seqopt jest specyficzne dla Microsoftu */

declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer

declarator:
pointeropt direct-declarator

direct-declarator: /* Deklarator funkcji */
direct-declarator ( parameter-type-list ) /* Deklarator w nowym stylu */
direct-declarator ( identifier-listopt ) /* Deklarator w przestarzałym stylu */

Prototyp ma taką samą postać jak definicja funkcji, z tą różnicą, że jest zakończony średnikiem bezpośrednio po nawiasie zamykającym i dlatego nie ma ciała. W obu przypadkach typ zwracany musi zgadzać się z typem zwracanym określonym w definicji funkcji.

Prototypy funkcji mają następujące ważne zastosowania:

  • Ustalają typ zwracany dla funkcji, które zwracają typy inne niż int. Chociaż funkcje zwracające wartości int nie wymagają prototypów, prototypy są zalecane.

  • Bez kompletnych prototypów dokonywane są standardowe konwersje, ale nie są podejmowane próby sprawdzenia typu lub liczby argumentów z liczbą parametrów.

  • Prototypy są używane do inicjalizacji wskaźników do funkcji, zanim te funkcje zostaną zdefiniowane.

  • Lista parametrów jest używana do sprawdzania zgodności argumentów w wywołaniu funkcji z parametrami w definicji funkcji.

Przekształcony typ każdego parametru określa interpretację argumentów, które wywołanie funkcji umieszcza na stosie. Niedopasowanie typu między argumentem a parametrem może spowodować, że argumenty na stosie zostaną źle zinterpretowane. Na przykład, na 16-bitowym komputerze, jeśli jako argument zostanie przekazany 16-bitowy wskaźnik, a następnie zadeklarowany jako parametr long, pierwsze 32 bity na stosie są interpretowane jako parametr long. Ten błąd powoduje problemy nie tylko z parametrem long, ale także z wszystkimi parametrami, które po nim następują. Błędy tego rodzaju można wykryć, deklarując pełne prototypy funkcji dla wszystkich funkcji.

Prototyp określa atrybuty funkcji, dzięki czemu wywołania funkcji poprzedzające jej definicję (lub występujące w innych plikach źródłowych) mogą być sprawdzane pod kątem niedopasowania typu argumentu i typu zwracanego. Na przykład, jeśli określisz static specyfikator klasy przechowywania w prototypie, musisz również określić static klasę przechowywania w definicji funkcji.

Kompletne 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 każdego wyrażenia, które jest przekazywane jako argument. Jednakże, takie identyfikatory mają zakres 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, niedopasowania mogą nie zostać ujawnione, więc kompilator nie może wygenerować dotyczących ich komunikatów diagnostycznych. Zobacz Argumenty, aby uzyskać więcej informacji na temat sprawdzania typów.

Zakres prototypów w kompilatorze Microsoft C jest teraz zgodny z ANSI, gdy kompiluje się z opcją kompilatora /Za. Oznacza to, że jeśli zadeklarujesz znacznik struct lub union wewnątrz prototypu, zostanie on wprowadzony w tym zakresie, a nie w zakresie globalnym. Na przykład, gdy kompilujesz z opcją /Za dla zgodności z ANSI, nie możesz wywołać tej funkcji bez otrzymania błędu niedopasowania typu:

void func1( struct S * );

Aby poprawić swój kod, zdefiniuj lub zadeklaruj znacznik struct lub union w zakresie globalnym przed prototypem funkcji:

struct S;void func1( struct S * );

Pod opcją /Ze, znacznik jest nadal wprowadzany w zakresie globalnym.

Zobacz także

Funkcje

.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.