Funktionsdeklaration ist kein Prototyp

158

Ich habe eine Bibliothek, die ich erstellt habe.

mylib.c:

#include <mylib.h>
int
testlib() {
    printf("Hello world\n");
    return (0);
}

mylib.h:

#include <stdio.h>
extern int testlib();

In meinem Programm habe ich versucht, diese Bibliotheksfunktion aufzurufen:

myprogram.c:

#include <mylib.h>

int
main (int argc, char *argv[]) {
    testlib();
    return (0);
}

Wenn ich versuche, dieses Programm zu kompilieren, wird folgende Fehlermeldung angezeigt:

In der Datei aus myprogram.c: 1
mylib.h: 2 Warnung: Funktionsdeklaration ist kein Prototyp

Ich benutze: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

Meine Frage ist, wie man einen Funktionsprototyp richtig deklariert.

Alan H.
quelle
1
Entfernen Sie extern aus der Deklaration in mylib.h. Insbesondere wenn Sie ein reines C-Programm schreiben, ist die externe Deklaration dort nicht erforderlich.
Ryan Ahearn

Antworten:

333

In C int foo()und int foo(void)sind verschiedene Funktionen. int foo()akzeptiert eine beliebige Anzahl von Argumenten, während int foo(void)0 Argumente akzeptiert werden. In C ++ bedeuten sie dasselbe. Ich schlage vor, dass Sie voidkonsequent verwenden, wenn Sie keine Argumente meinen.

Wenn Sie eine Variable haben a, extern int a;können Sie dem Compiler mitteilen, dass aes sich um ein Symbol handelt, das möglicherweise in einer anderen Übersetzungseinheit vorhanden ist (C-Compiler spricht für Quelldatei). Lösen Sie diese erst nach der Verbindungszeit auf. Andererseits werden Symbole, die Funktionsnamen sind, zum Zeitpunkt der Verknüpfung ohnehin aufgelöst. Die Bedeutung eines Speicherklassenspezifizierers für eine Funktion ( extern, static) wirkt sich nur auf deren Sichtbarkeit aus und externist die Standardeinstellung, sodass sie externeigentlich nicht erforderlich ist.

Ich schlage vor, das zu entfernen extern, es ist irrelevant und wird normalerweise weggelassen.

Pramod
quelle
9
Verwenden Sie (void) in C, um anzugeben, dass eine Funktion keine Argumente akzeptiert. Verwenden Sie in C ++ nur, wenn Sie Ihren Code nicht speziell zum Kompilieren als C und als C ++ benötigen ().
Keith Thompson
49

Schnelle Antwort: Wechseln Sie int testlib()zu, int testlib(void)um anzugeben, dass die Funktion keine Argumente akzeptiert.

Ein Prototyp ist per Definition eine Funktionsdeklaration, die den Typ (die Typen) der Argumente der Funktion angibt.

Eine Nicht-Prototyp-Funktionsdeklaration wie

int foo();

ist eine Deklaration im alten Stil, die weder die Anzahl noch die Art der Argumente angibt. (Vor dem ANSI C-Standard von 1989 war dies die einzige in der Sprache verfügbare Funktionsdeklaration.) Sie können eine solche Funktion mit einer beliebigen Anzahl von Argumenten aufrufen, und der Compiler muss sich nicht beschweren - aber wenn die Aufruf ist nicht mit der Definition vereinbar , Ihr Programm hat undefiniertes Verhalten.

Für eine Funktion, die ein oder mehrere Argumente akzeptiert, können Sie den Typ jedes Arguments in der Deklaration angeben:

int bar(int x, double y);

Funktionen ohne Argumente sind ein Sonderfall. Logischerweise wären leere Klammern eine gute Möglichkeit gewesen, um anzugeben, dass ein Argument, aber diese Syntax bereits für Funktionsdeklarationen alten Stils verwendet wurde. Daher hat das ANSI C-Komitee eine neue Syntax mit dem voidSchlüsselwort erfunden :

int foo(void); /* foo takes no arguments */

Eine Funktionsdefinition (der Code enthält , was die Funktion macht tatsächlich) liefert auch eine Erklärung . In Ihrem Fall haben Sie etwas Ähnliches wie:

int testlib()
{
    /* code that implements testlib */
}

Dies bietet eine Nicht-Prototyp-Deklaration für testlib. Als Definition teilt dies dem Compiler mit, testlibder keine Parameter hat, aber als Deklaration teilt er nur dem Compiler mit, testlibder eine nicht spezifizierte, aber feste Anzahl und Art von Argumenten akzeptiert.

Wenn Sie ()zur (void)Deklaration wechseln , wird ein Prototyp.

Der Vorteil eines Prototyps besteht darin, dass testlibder Compiler den Fehler diagnostiziert , wenn Sie versehentlich mit einem oder mehreren Argumenten aufrufen .

(C ++ hat leicht abweichende Regeln. C ++ hat keine Funktionsdeklarationen im alten Stil, und leere Klammern bedeuten speziell, dass eine Funktion keine Argumente akzeptiert. C ++ unterstützt die (void)Syntax für die Konsistenz mit C. Es sei denn, Sie benötigen Ihren Code speziell, um beide als zu kompilieren C und als C ++ sollten Sie wahrscheinlich die ()in C ++ und die (void)Syntax in C verwenden.)

Keith Thompson
quelle
22

Versuchen:

extern int testlib(void);
Lasse V. Karlsen
quelle