2016-03-30 11 views
3

Der Code folgt keine Warnungen ausgeben, wenn sie mit beiden gcc und clang auf Linux x64 zusammengestellt:Sind mehrere identische Prototypen legal?

Alle Erklärungen, die Bezug zu nehmen:

#include <stdio.h> 
#include <stdlib.h> 

void foo(void); 

void foo(void); 

void foo(void); 

int main(void) 
{ 
    return 0; 
} 

IMO, es die folgenden Auszüge aus C99 nach legal das gleiche Objekt oder die gleiche Funktion muss kompatiblen Typ haben; Andernfalls ist das Verhalten nicht definiert.

(...)

Für zwei Funktions Typen kompatibel zu sein, müssen beide kompatible Typen Rückkehr angeben

(...)

Darüber hinaus sind die Parameter Typenlisten, wenn beide vorhanden sind, sollen in der Anzahl der Parameter und in der Verwendung der Ellipse Terminator übereinstimmen; entsprechende Parameter müssen kompatible Typen haben.

(...)

Zwei Typen haben kompatible Typen, wenn ihre Typen gleich sind.

Bin ich richtig? Ich möchte sicherstellen, dass es nicht UB ist und dass mein Verständnis korrekt ist.

+3

C-Standard ist C11. Verwenden Sie keine ungültigen veralteten Versionen des Standards für Diskussionen. – Olaf

+1

Sie könnten es c99 anstelle von c taggen, wenn Sie wirklich c99 verwenden – bruceg

+1

'wenn Sie wirklich c99 verwenden '- Ich habe gehört, dass die meisten Compiler noch nicht alle' C99' Features, geschweige denn 'C11' so implementiert habe ich frage mich, was du mit "wirklich mit C99" meinst – user1042840

Antwort

4

Mehrere identische Prototypen sind legal, und tatsächlich üblich, weil es im modernen C typisch ist, dass eine Funktionsdefinition einen Prototyp für diese Funktion umfasst, und dass es auch einen Prototyp für die Funktion im Bereich der Einbeziehung von gibt eine Header-Datei. Das heißt, da

foo.h:

void foo(int x); 

foo.c:

#include "foo.h" 

void foo(int x) { 
    printf("%d\n", x); 
} 

/* ... */ 

gibt es zwei identische Prototypen für foo() in ihrem Umfang in den Körper Funktion foo ' s Definition und im gesamten Rest der Datei. Das ist in Ordnung.

Es ist auch mehrere Erklärungen des gleichen Objekts oder einer Funktion, die nicht identisch, solange sie sind kompatibel haben ok. Zum Beispiel kann die Erklärung

void foo(); 

erklärt foo als eine Funktion nicht spezifizierte Parameter zu nehmen und nichts zurück. Diese Deklaration ist kompatibel mit denen, die bereits in foo.c und foo.h vorhanden sind, und sie könnte zu einer oder beiden dieser Dateien hinzugefügt werden, ohne zusätzlichen Effekt.

Und das gilt auch für Objekte (Variablen), wo einige Anwendungen ziemlich häufig sind. Wenn Sie beispielsweise eine globale Variable deklarieren möchten, auf die aus mehreren Dateien zugegriffen wird, ist es üblich, eine Deklaration dieser Variablen in eine Header-Datei aufzunehmen.Die C-Quelldatei enthält, und die Definition dieser Variablen - die auch eine Erklärung ist - typischerweise #include s der Header, wodurch man zwei Erklärungen:

global.h:

extern int global; 

global. c:

#include "global.h" 

int global = 42; 

Oder es ist der Fall von Forward-Deklaration von Verbindung Datentypen:

struct one; 

struct two { 
    struct one *my_one; 
    struct two *next; 
}; 

struct one { 
    struct two *my_two; 
} 

Beachten Sie die mehrfach kompatiblen, aber nicht identischen Deklarationen von struct one. Diese bestimmte Gruppe von Datenstrukturen kann überhaupt nicht deklariert werden, ohne eine der Arten mehrfach zu deklarieren.

+0

Guter Punkt über wiederholte Prototyp in einer Definition - ich habe nicht einmal darüber nachgedacht! – user1042840

+0

Noch eine Sache - wenn Sie Zeit haben, können Sie bestätigen, dass ich darüber nachdenke, welche Teile im 'C99' oder' C11' Standard dieses Verhalten korrekt beschreiben, oder sollte ich nach einer Erklärung in einem ganz anderen Teil des Standards suchen? Vor kurzem fing ich an, offizielle Standards zu lesen, sie scheinen am Anfang sehr schwer zu verstehen, je mehr Sie lesen, desto mehr verstehen Sie. – user1042840

+0

I_think_ 'void foo() {...}' als eine Funktion _definition_ ist das gleiche wie 'void foo (void) {...}' wohingegen _declaration_ 'void foo()' nicht dasselbe ist wie 'void foo (void) '. (C99). Deine Gedanken oder ist das außerhalb des Postbereichs? – chux