Warum ist #einschließen nicht erforderlich, um printf() zu verwenden?

Lesezeit: 4 Minuten

Benutzer-Avatar
Konstantin

Sitzungsmitschrift:

> type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

> cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

> lookma
no stdio.h

  • Beachten Sie, dass Sie in C89/C90 einen Rückgabewert von angeben sollten main(). C99 erlaubt das Weglassen return 0; oder gleichwertig ab Ende main().

    – Jonathan Leffler

    30. Oktober 2015 um 2:30 Uhr

  • In welchem ​​Zusammenhang? Befehlszeilenfenster an Windows?

    – Peter Mortensen

    26. April 2021 um 12:39 Uhr

Benutzer-Avatar
Chris Jung

Sie hatten dieses C++ ursprünglich markiert, aber es scheint ein C-Programm zu sein. C stellt automatisch eine implizite Deklaration für eine Funktion bereit, wenn kein Prototyp im Gültigkeitsbereich vorhanden ist (z. B. aufgrund des Weglassens von #include ). Die implizite Deklaration wäre:

int printf();

Das bedeutet, dass printf eine Funktion ist, die ein int zurückgibt und eine beliebige Anzahl von Argumenten annehmen kann. Dieser Prototyp hat zufällig für Ihren Anruf funktioniert. Sie sollten #einschließen

Abschließend sollte ich hinzufügen, dass der aktuelle C-Standard (ISO/IEC 9899:1999 oder umgangssprachlich „C99“) dies tut nicht erlaubt implizite Deklarationen, und dieses Programm wäre nicht konform. Implizite Deklarationen wurden entfernt. Ich glaube, Ihr Compiler unterstützt C99 nicht. C++ erfordert auch korrekte Prototypen und führt keine impliziten Deklarationen durch.

Benutzer-Avatar
Jonathan Leffler

Im strikten Compliance-Modus (das bedeutet „theoretisch“) rufen Sie ein undefiniertes Verhalten auf (was schlecht ist), wenn Sie eine Funktion aufrufen, die eine variable Anzahl von Argumenten ohne eine Prototypdeklaration der Funktion im Gültigkeitsbereich akzeptiert. Das bedeutet, dass der Compiler mit einem Programm, das verwendet, machen darf, was er will printf() ohne den Prototyp aus #include <stdio.h> oder eine gleichwertige Erklärung. “Alles, was es mag” schließt das korrekte Arbeiten als eine der Optionen ein; das scheint die von Ihrem Beispiel gewählte Option zu sein.

In der Praxis funktioniert der Code mit den meisten praktischen Compilern auch ohne die formelle Deklaration der printf() Funktion.

Wie von qrdl darauf hingewiesen wurde, wurde die Funktion gefunden, weil der C-Compiler mit der C-Bibliothek verknüpft ist.

Beachten Sie, dass Chris Youngs Kommentar zu C99 und „implicit int“ korrekt ist, aber die Regel „Funktionen mit variablen Argumenten müssen einen Prototyp im Geltungsbereich haben“ gilt sowohl für C89 als auch für C99. Die meisten Compiler arbeiten standardmäßig nicht in einem strengen C99-Kompatibilitätsmodus, da es zu viel Code gibt, der nicht so kompiliert werden würde.

Chris Young kommentierte:

Zur Verdeutlichung bezog sich mein Kommentar darauf, dass C99 implizite Deklarationen entfernt. Wenn Sie “implicit int” sagen, beziehen Sie sich meiner Meinung nach auf die C89-Funktion, Deklarationen wie foo(void) zuzulassen. bedeutet int foo(void);, etwas, das C99 auch entfernt hat.

Chris hat natürlich Recht. Aus dem C99-Standard wurden zwei Merkmale der „impliziten Deklaration“ entfernt. Das Vorwort der Norm listet sie auf als:

  • implizit entfernen int
  • Implizite Funktionsdeklaration entfernen

Ich habe nicht klar genug gedacht (und daher auch nicht geschrieben). Trotzdem erfordern sowohl C89 als auch C99 einen Prototyp im Geltungsbereich für Funktionen, die eine variable Anzahl von Argumenten annehmen.

Um zu zeigen:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

Ohne die erste Zeile ist dies ein korrektes C89-Fragment mit einer impliziten Deklaration der Funktion pqr() als eine Funktion, die eine ganze Zahl zurückgibt (mit nicht spezifizierten Argumenten). Wenn die erste Zeile ersetzt wird durch extern pqr();dann ist dies ein korrektes C89-Fragment mit einer expliziten Deklaration von pqr() als eine Funktion, die eine Ganzzahl zurückgibt (mit nicht spezifizierten Argumenten), aber der Rückgabetyp ist „implizit int‘. Wie geschrieben, wird die Funktion explizit deklariert und hat eine explizite int Rückgabetyp – aber es hat immer noch nicht spezifizierte Argumente. Ich glaube, das ist gültig C99 – wenn auch nicht ganz wünschenswert. Natürlich akzeptiert GCC (3.4.4) es mit den Optionen ‘-std=c99 -pedantic“. Idealerweise sollte die Funktionsdeklaration den vollständigen Prototyp enthalten. (Und, falls pqr() mit Auslassungspunkten definiert wurden, wäre dieser Prototyp erforderlich in der Theorie!)

  • Zur Verdeutlichung bezog sich mein Kommentar darauf, dass C99 implizite Deklarationen entfernt. Wenn Sie “implicit int” sagen, beziehen Sie sich meiner Meinung nach auf die C89-Funktion, Deklarationen wie foo(void) zuzulassen. bedeutet int foo(void);, etwas, das C99 auch entfernt hat.

    – Chris Jung

    5. Dezember 2008 um 10:24 Uhr

Benutzer-Avatar
qrdl

printf() befindet sich in der Standard-C-Bibliothek und der Linker verknüpft die Standardbibliothek immer mit Ihrer ausführbaren Datei, sodass alle Standardfunktionen gefunden werden und es keine Verknüpfungsprobleme gibt.

Wird der entsprechende Header nicht eingefügt, führt dies zur Verwendung einer Funktion, für die kein Prototyp erstellt wurde, was zu Problemen führen kann, da der C-Compiler davon ausgeht, dass eine Funktion ohne Prototyp zurückgegeben wird int und nimmt eine variable Anzahl von Argumenten an. Fügen Sie also immer den Header hinzu – es ist Ihr Sicherheitszaun.

  • Keine ‘variable Anzahl von Argumenten’, sondern eine undefinierte, aber feste Anzahl von Argumenten.

    – Jonathan Leffler

    4. Dezember 2008 um 20:27 Uhr

1383780cookie-checkWarum ist #einschließen nicht erforderlich, um printf() zu verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy