C-Funktionsaufrufe: Die Regel "implicit int" verstehen

  • <">

    Wenn" eine Funktion "separat kompiliert würde, würde die Nichtübereinstimmung nicht erkannt," die Funktion "würde ein doppeltes Ergebnis zurückgeben, das Main als Int ... behandeln würde Das Licht von dem, was wir darüber gesagt haben, wie Deklarationen mit Definitionen übereinstimmen müssen, erscheint vielleicht überraschend. Der Grund für eine Nichtübereinstimmung besteht darin, dass eine Funktion implizit deklariert wird, wenn es keinen Funktionsprototyp gibt, wie zum Beispiel

         sum += "the function"(line);
     

    Wenn ein Name, der noch nicht deklariert wurde, in einem Ausdruck vorkommt und von einer linken Klammer gefolgt wird, wird er als Kontext deklariert Bei einem Funktionsnamen wird davon ausgegangen, dass die Funktion ein int zurückgibt, und es wird nichts über ihre Argumente angenommen.

    Ich entschuldige mich im Voraus für die mehrdeutige Frage, aber Was bedeutet das?

    Übrigens ist dies auf Seite 73, Kapitel 4.3 von Brian W. Kernighan und Dennis M. Ritchies C Programming Language-Buch, 2. Auflage.

    22 November 2011
    Keith Thompson
3 answers
  • K & amp; R2 deckt die 1989/1990-Version der Sprache ab. Der aktuelle ISO-C-Standard, der in 1999 2011 veröffentlicht wurde, hebt die "implicit int" -Regel auf und erfordert für jede aufgerufene Funktion eine sichtbare Deklaration. Compiler erzwingen dies nicht unbedingt standardmäßig, aber Sie sollten in der Lage sein, strengere Warnungen anzufordern - und Sie sollten dies auf jeden Fall tun. In gut geschriebenem neuem Code ist die Regel irrelevant (muss jedoch verstanden werden).

    Ein Beispiel: Die Standardfunktion sqrt() ist in <math.h> deklariert:

     double sqrt(double);
     

    Wenn Sie einen Anruf ohne die erforderlichen #include <math.h> schreiben:

     double x = 64.0;
    double y = sqrt(x);
     

    Ein C90-Compiler geht davon aus, dass sqrt int - und zurückgibt Es wird Code generiert, um das Ergebnis von int in double umzuwandeln. Das Ergebnis ist Müll oder vielleicht ein Absturz.

    (Sie könnten manuell sqrt selbst deklarieren, aber das ist die falsche Lösung.)

    Also machen Sie das nicht. Fügen Sie immer den Kopf hinzu, der für jede aufgerufene Funktion erforderlich ist. Sie könnten eine nicht deklarierte Funktion aufrufen, wenn sie int zurückgibt (und wenn Ihr Compiler keine strikte C99- oder C11-Semantik erzwingt und wenn einige andere Bedingungen erfüllt sind), aber es gibt keinen Grund, dies zu tun.

    Das Verständnis der "implicit int" -Regel ist immer noch hilfreich, um das Verhalten von altem oder schlecht geschriebenem Code zu verstehen, aber Sie sollten sich niemals auf neuen Code verlassen.

    18 October 2017
    Keith Thompson
  • Funktionsprototypen wurden spät in die Sprache eingeführt.

    Vor Prototypen würde der Compiler annehmen, dass jedes an jede unbekannte Funktion übergebene Argument als Ganzzahl und übergeben werden sollte Ich würde annehmen, dass der Rückgabewert auch eine ganze Zahl war.

    Dies funktionierte gut für die wenigen Fälle, in denen es richtig war, aber die Leute mussten Programme in einer unpraktischen Reihenfolge schreiben, so dass dies funktioniert würde sich niemals auf unbekannte Funktionen verlassen, die nicht dieser Erwartung entsprachen.

    Als Prototypen in C89 (alias ANSI C oder ISO C), den Prototypen, eingeführt wurden Ermöglichen Sie dem Compiler, genau zu wissen, welche Arten von Argumenten erwartet werden und welche Arten von Ergebnissen zurückgegeben werden.

    Es wird dringend empfohlen, Funktionsprototypen für alle neuen Codes zu verwenden. Wenn auf einer völlig alten Codebasis gearbeitet wird, können die Prototypen schädlich sein. (Oder wenn der Code auf einem Compiler vor ANSI C kompiliert werden muss, sollten Sie die Prototypen weglassen, damit sie auf der alten Software basieren können. gcc ist der einzige Ort, an dem ich dies in a gesehen habe lange Zeit.)

    22 November 2011
    sarnoldRocco
  • Es heißt nur, dass der Compiler, wenn er auf Code stößt, der eine unbekannte Funktion aufruft, implizit so behandelt, als hätte er bereits einen deklarierten Prototyp der Form int unknown();

    gesehen
    22 November 2011
    R. Martinho Fernandes