Frage

Um wirklich standardkonforme, müssen alle Funktionen in C (mit Ausnahme der Haupt) einen Prototyp, auch wenn sie erst nach ihrer Definition in der gleichen Übersetzungseinheit verwendet werden?

War es hilfreich?

Lösung

Es hängt davon ab, was Sie unter ‚wirklich standardkonform‘. Allerdings ist die kurze Antwort ist „es ist eine gute Idee, um sicherzustellen, dass alle Funktionen einen Prototyp in Umfang haben bevor sie verwendet werden“.

Eine qualifizierte Antwort stellt fest, dass, wenn die Funktion variable Argumente akzeptiert (insbesondere die printf() Familie von Funktionen), dann ein Prototyp in Umfang sein muss streng standardkonform zu sein. Dies gilt für C89 (von ANSI) und C90 (von ISO, ebenso wie C89 mit Ausnahme der Abschnittsnummerierung). Anders als ‚varargs‘ Funktionen, aber Funktionen, die ein int zurückkehren müssen erklärt und Funktionen nicht, die etwas anderes als ein int zurückkehren tun, um eine Erklärung benötigen, die den Rückgabetyp zeigt aber nicht den Prototyp für die Argumentliste benötigen.

Beachten Sie jedoch, dass, wenn die Funktion Argumente übernimmt, die ‚normale Aktionen‘ in Abwesenheit von Prototypen unterliegen (zum Beispiel eine Funktion, die ein char oder short nimmt - die beide umgewandelt int, ernster, vielleicht, eine Funktion, die eine float anstelle eines double nimmt), dann wird ein Prototyp benötigt. Der Standard war lax über diese alten C-Code zu ermöglichen, unter Standard-konformen Compiler zu kompilieren; älterer Code wurde nicht darum, sicherzustellen, sorgt geschrieben, dass Funktionen vor dem Gebrauch erklärt wurden -. und per definitionem älterer Code Prototypen nicht verwenden, da sie nicht in C verfügbar worden sind, bis ein Standard war

C99 nicht zulässt ‚impliziten int‘ ..., die sowohl oddball Fälle wie ‚static a;‘ ist (ein int Standardeinstellung) und auch implizite Funktionsdeklarationen. Diese werden erwähnt (zusammen mit etwa 50 anderen wichtigen Änderungen) im Vorwort zu ISO / IEC 9899: 1999, Welches vergleicht diesen Standard zu den vorherigen Versionen:

  
      
  • entfernen implizite int
      ...
  •   
  • entfernt implizite Funktionsdeklaration
  •   

In der ISO / IEC 9899: 1990, §6.3.2.2 Funktionsaufrufe angegeben:

  

Wenn der Ausdruck, den die eingeklammerten Argumentliste in einem Funktionsaufruf voran besteht   ausschließlich aus einer Kennung, und wenn keine Erklärung für diese Kennung sichtbar ist, ist die Kennung implizit   erklärt genau, als ob in den innersten Block den Funktionsaufruf enthält, die Deklaration:

extern int identifier();
     

erschien. 38

     

38 Das heißt, erklärte eine Kennung mit Block Umfang mit Typ-Funktion externe Bindung zu haben, ohne   Parameterinformationen und eine int zurück. Wenn in der Tat ist es nicht als mit Typ „definierte Funktion   Rückkehr int“, ist das Verhalten nicht definiert.

Dieser Absatz ist im 1999 Standard fehlt. Ich habe (noch) nicht verfolgen die Änderung des Wortschwalls, die static a; in C90 erlaubt und verbietet es (erfordern static int a;) in C99.

Beachten Sie, dass, wenn eine Funktion statisch ist, definiert werden kann, bevor es verwendet wird, und muss nicht durch eine Erklärung vorangestellt werden. GCC kann Witter dazu gebracht werden, wenn eine nicht-statische Funktion ohne eine Erklärung definiert ist vorausgehend (-Wmissing-prototypes).

Andere Tipps

A Prototyp ist eine Funktionsdeklaration, die die Typen der Funktion der Parameter angibt.

Vor dem ANSI C (die Sprache beschrieben durch die 1978 erste Ausgabe von Kernighan & Ritchie "The C Programming Language") nicht Prototypen haben; es war nicht möglich, dass eine Funktionsdeklaration die Anzahl oder die Typen der Parameter zu beschreiben. Es war bis zu dem Anrufer die korrekte Anzahl und Art des Arguments zu übergeben.

ANSI C eingeführt "Prototypen", Erklärungen, die die Typen der Parameter (ein Feature, entlehnt von Anfang C ++) angeben.

Wie von C89 / C90 (die ANSI und ISO-Normen beschreiben die gleiche Sprache), es ist legal, eine Funktion ohne sichtbare Erklärung zu nennen; eine implizite Erklärung vorgesehen. Wenn die implizite Deklaration ist unvereinbar mit der tatsächlichen Definition (sagen wir, ruft sqrt("foo"), dann ist das Verhalten nicht definiert. Weder diese implizite Deklaration noch eine Nicht-Prototyp Erklärung kann mit einer variadische Funktion kompatibel sein, so dass jeder Anruf an eine variadische Funktion (wie printf oder scanf) muss einen gut sichtbaren Prototyp hat.

C99 fiel implizite Erklärungen. Jeder Aufruf an eine Funktion ohne eine sichtbare Angabe ist eine Einschränkungsverletzung, erfordert ein Compiler Diagnose. Aber diese Erklärung ist erforderlich, noch kein Prototyp sein; es kann eine im alten Stil Erklärung, die nicht Parametertypen nicht angeben.

C11 machten keine wesentlichen Änderungen in diesem Bereich.

So, selbst als der 2011 ISO-C-Standard, im alten Stil Funktionsdeklarationen und Definitionen (die seit 1989 "obsolescent" werden) sind nach wie vor in konformem Code erlaubt.

Für alle Versionen von C bis 1989 zurück, als eine Frage des Stils, gibt es sehr wenig Grund, nicht Prototypen für alle Funktionen zu nutzen. Im alten Stil Erklärungen und Definitionen gehalten werden nur alten Code zu brechen zu vermeiden.

Nein, Funktionen müssen nicht immer einen Prototyp. Die einzige Voraussetzung ist, dass eine Funktion „erklärt“ werden, bevor Sie es benutzen. Es gibt zwei Möglichkeiten, eine Funktion zu deklarieren: ( „Definition“ genannt), einen Prototyp zu schreiben, oder die Funktion selbst schreiben Eine Definition ist immer eine Erklärung, aber nicht alle Erklärungen sind Definitionen

.

Ja, muss jede Funktion einen Prototyp, aber das Prototyp kann entweder in einer gesonderten Erklärung oder als Teil der Funktion der Definition erscheinen. Funktionsdefinitionen in C89 geschrieben und auf natürliche Weise Prototypen haben, aber wenn Sie schreiben Dinge im klassischen K & R-Stil, also:

main (argc, argv)

  int argc;
  char **argv;

{
  ...
}

hat dann die Funktionsdefinition keinen Prototyp. Wenn Sie schreiben, ANSI C (C89) Stil, also:

main (int argc, char **argv) { ... }

hat dann die Funktionsdefinition einen Prototyp.

Ein schöner Tipp, wenn neue Funktionen schreiben, ist sie upside-down mit Haupt am Boden so zu schreiben, wenn Sie Ihre Meinung über die args der Funktion ändern oder Typen zurückgeben Sie müssen auch den Prototyp nicht zu beheben. Ständig Prototypen Befestigung und der Umgang mit den Warnungen des all Compiler, wenn sie veraltet sind bekommt wirklich langweilig.

Sobald Sie Ihre Funktionen reibungslos zusammenarbeiten, um den Code zu einem gut benannte Modul bewegen und die Prototypen in einer .h-Datei mit dem gleichen Namen setzen. Es spart schwere Zeit. Die größte Produktivität Hilfe Ich habe in 5 Jahren gefunden.

Nach bestem Wissen und Gewissen (in ANSI C89 / ISO C90), Nr. Ich bin nicht sicher C99; jedoch würde ich das gleiche erwarten.

Persönliche Anmerkung: Ich habe nur Funktionsprototypen schreiben, wenn ...

  1. Ich muss (wenn A () ruft B () und B () ruft A ()) oder
  2. Ich Export der Funktion; sonst, es fühlt sich überflüssig.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top