2014-12-31 7 views
7

Ich habe mit GCC experimentiert und festgestellt, dass Sie externe Variablen const in Header-Dateien deklarieren können, sie aber in Implementierungsdateien veränderbar halten.Deklaration einer globalen Variable `extern const int` im Header aber nur` int` in der Quelldatei

BEARBEITEN: Das funktioniert eigentlich nicht. Der einzige Grund, warum ich meinen Testcode kompilieren ließ, war, dass ich "header.h" nicht in "header.c" eingefügt habe.

header.h:

#ifndef HEADER_H_ 
#define HEADER_H_ 

extern const int global_variable; 

#endif 

header.c:

int global_variable = 17; 

Dies scheint ein sehr gutes Feature für die Verwendung global_variable nur lesbar für die Nutzer von header.h zu halten, aber sie modifable durch die Beibehaltung Implementierung (header.c).

HINWEIS: Der folgende Code ist nur ein Beispiel dafür, wie diese Art der Deklaration die Zuweisung an global_variable verhindert.

#include "header.h" 

int main(void) 
{ 
    global_variable = 34; /* This is an error as `global_variable` is declared const */ 
    return 0; 
} 

Weil ich noch nie Technik in der Praxis gesehen. Ich frage mich, ob es gültig ist.

Ist das wohl definiertes Verhalten oder ist das ein Fehler, vor dem GCC mich nicht warnen kann?

+0

Was ist der genaue Wortlaut des Fehlers (kopieren und einfügen)? –

+0

Ich würde es verwirrend finden, dass sich eine const-Variable überhaupt ändern könnte. Ich würde den Bereich mit statisch beschränken und eine Funktion bereitstellen, um den aktuellen globalen Wert zurückzugeben, um denselben Effekt zu erzielen. – ryanpattison

+1

Das funktioniert nur, wenn header.h in header.c ** nicht ** enthalten ist. Wenn man header.h in header.c einfügt, führt die Zuweisung ** zu einem Syntaxfehler. Wenn das in einem echten Programm mit 1000 Zeilen Code gemacht wird und etwas damit nicht stimmt - wie leicht wird es repariert werden? –

Antwort

6

const int und int sind nicht kompatible Typen.

Zum Beispiel dieses:

extern const int a; 

int a = 2; 

ist nicht gültig in C als C sagt, dass:

(C11, 6.7p4) „Alle Erklärungen in dem gleichen Umfang, die auf das gleiche Objekt bezieht oder Funktion wird festgelegt, kompatible Typen“

in Ihrem Fall sind sie nicht in gleichem Umfang (verschiedene Übersetzungseinheiten), aber C sagt auch, dass:

(C11, 6.2.7p2) "Alle Deklarationen, die sich auf dasselbe Objekt oder dieselbe Funktion beziehen, müssen einen kompatiblen Typ haben; ansonsten ist das Verhalten nicht definiert.“

Wie Sie die Regel oben verletzen, Sie nicht definiertes Verhalten sind aufgerufen wird.

Beachten Sie, dass C90 die gleichen Ziffern hat.

+0

Ich denke OP ist _counting_ darauf nicht kompilieren. Wenn Code nicht kompiliert wird, gibt es kein UB. – chux

+0

@chux Ich verstehe Ihren Standpunkt nicht, könnten Sie das näher ausführen? Ich denke OP kompiliert und verbindet 'header.c' und' main.c' zusammen (ansonsten haben Sie keine Definition für das Objekt). – ouah

+0

NMDV, aber OP scheint zu wissen, dass der 'main.c' Code nicht kompiliert wurde. Die eigentliche Frage lautet: Kann eine nicht-konstante Variable in einem Modul als nicht-konstant und in einem anderen als const deklariert werden? – chux

0

Sie sind nicht Wert zuweisen global_variable, können Sie es definieren.

1

Ein wenig spät, aber sowieso.

ich denke, das funktionieren kann, wenn Sie so etwas wie dieses

tun

in der Kopfzeile.h:

#ifndef HEADER_H_ 
#define HEADER_H_ 

#ifndef HAS_GLOB_VAR 
extern const int global_variable; 
#endif 

#endif 

und wenn Sie die Header in der Datei enthalten sein, die tatsächlich die Variable definiert (header.c) Sie tun so etwas wie

#define HAS_GLOB_VAR 
#include "header.h" 

int global_variable = 17; 

... 

Auf der anderen Dateien, die Sie umfassen nur den Header und don definiere nicht HAS_GLOB_VAR.

+2

Hmm, das ist UB per (C11, 6.2.7p2) "Alle Deklarationen, die sich auf dasselbe Objekt oder dieselbe Funktion beziehen, müssen einen kompatiblen Typ haben; andernfalls ist das Verhalten nicht definiert." – chux