Fragen zu Header Dateien

Belchy

Cadet 1st Year
Dabei seit
Apr. 2011
Beiträge
9
Hallo zusammen,

ich habe ein mehr oder weniger großes Problem, wobei ich per googel keine zufriedenstellende Lösung gefunden habe. Ich hoffe ihr könnt mir hier weiter helfen :)

Folgendes:
Ich muss für ein Projekt etwas Programmieren. Das Programm an sich ist vorgegeben, und besitzt folgende C/H Dateien: Global.h, User.h, User.c, IO.h, IO.c
User.c und IO.c enthalten nur Funktionen.

Nun würde ich gerne eine Variable definieren, die in User.c, sowie in IO.c verwendet werden kann.
Sinnvollerweise sollte man dies wohl in der Global.h machen, was ich auch gemacht habe.
Weiter ist Global.h auch in allen anderen der 4 Dateien oben per #include eingebunden.

Wenn ich jetzt z.b eine Variable "extern int test;" in Global.h definiere, und sie in einer Funktion! in User.c aufrufen will (z.b mit "test++;"), bekomme ich beim kompilieren folgende Fehlermeldung:

Error in function XXX: 'test' undeclared (first use in this function)

Woran könnte das liegen?
Ich hoffe ihr könnt mir weiterhelfen.


Grüße,
Belchy
Wie kann das sein, obwohl ich doch meine Variable ei
 

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Du bist 100%-ig sicher, daß du den Header in User.c auch wirklich inkludierst?
 

leboh

Ensign
Dabei seit
Mai 2010
Beiträge
167
in User.c fehlt ein
int test;

extern int ist eine Deklaration, was noch fehlt ist eine Definition. Eine.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
Ja. Ich habe gerade nochmal nachgeschaut. Das war ja das was mich wundert, denn normal sollte sie ja dann verfügbar sein.
Ergänzung ()

Oh man. Darauf hätte ich auch selber kommen können ;)
Danke.

Wenn ich die gleiche Variable nun auch in IO.c verwenden will, muss ich sie dort dann auch nochmal definieren?
Nicht das durch das definieren eine neue Variable erzeugt wird. Oder wird das automatisch durch den Compiler anhand des extern erkannt?
 
Zuletzt bearbeitet:

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Zitat von leboh:
in User.c fehlt ein
int test;

extern int ist eine Deklaration, was noch fehlt ist eine Definition. Eine.

Das sollte dann zu einem Linkerfehler führen. Der OP ist aber schon beim Kompilieren auf die Nase gefallen.

Zitat von Belchy:
Ergänzung ()

Wenn ich die gleiche Variable nun auch in IO.c verwenden will, muss ich sie dort dann auch nochmal definieren?

Nein. Nur eine Definition. Sonst wird der Linker sauer auf dich und schimpft über mehrfach definierte Symbole.
Ergänzung ()

Zitat von Belchy:
Ja. Ich habe gerade nochmal nachgeschaut. Das war ja das was mich wundert, denn normal sollte sie ja dann verfügbar sein.

Hmm, komisch. Kannst du vielleicht mal deinen Header und deine user.c hier posten?
 
Zuletzt bearbeitet:

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
Ich habs jetzt grad eben mal getestet. Wenn ich in User.c "int test;" schreibe, meckert der Compiler nicht, wenn ich die Variable in einer Funktion dort aufrufe.

Wenn ich jetzt jedoch in einer Funktion in IO.c die Variable verändern will, kommt der gleiche Fehler wie vorhin.
Kann das daran liegen, dass User.c nicht in IO.c eingebunden ist? (Ist so vorgegeben).
Wenn ja, muss ich sie dann nicht nochmal definieren?
Ergänzung ()

ich kann eventuell einen kurzen Teil posten, da das Programm an sich nicht mir gehört.

global.h:

#ifndef _GLOBAL_H__
#define _GLOBAL_H__

#if defined(DSPACE)
# include <ipgrt.h>
#endif

#if defined(INTIME) || defined(ARTE_INTIME)
# if defined(__GNUC__)
# include <intime.h>
# endif
#endif

#if !defined(__GNUC__)
# if !defined(__inline__)
# if defined(_MCCPPC)
# define __inline__ inline
# else
# define __inline__ /* nothing */
# endif
# endif
# if !defined(__attribute__)
# define __attribute__(x) /* nothing */
# endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

extern int test;


#ifdef __cplusplus
}
#endif

#endif /* !defined(_GLOBAL_H__) */


user.c

#include <global.h>

int test;

void calc(){
test++;
}

io.c
sieht im prinzip genauso aus wie user.c, nur mit anderen funktionen
 
Zuletzt bearbeitet:

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Zitat von Belchy:
Ich habs jetzt grad eben mal getestet. Wenn ich in User.c "int test;" schreibe, meckert der Compiler nicht, wenn ich die Variable in einer Funktion dort aufrufe.

Wenn ich jetzt jedoch in einer Funktion in IO.c die Variable verändern will, kommt der gleiche Fehler wie vorhin.
Kann das daran liegen, dass User.c nicht in IO.c eingebunden ist? (Ist so vorgegeben).
Wenn ja, muss ich sie dann nicht nochmal definieren?


Halt halt halt!! ;)
Zwar hat leboh Recht, wenn er sagt, daß irgend wo in deinem Programm auch eine Definition für test vorhanden sein muß, aber das hat mit deinem Kompilierfehler erst mal GAR NIX zu tun. Nimm die Definition von test erst mal wieder aus deiner User.c raus, denn damit verdeckst du das eigentlich Problem nur.

Ich denke immer noch, daß du deine global.h nicht inkludierst, oder zumindest nicht KORREKT inkludierst. Zwei mögliche Fehlerursachen fallen mir ein:

  • Du ziehst zwar Global.h ein, aber nicht die Globa.h, die du möchtest. Vielleicht gibt's noch eine andere Global.h, die stattdessen hergenommen wird.
  • Du verwendest in mehreren Headerdateien fälschlicherweise die gleichen include guards.

    Code:
    // in header bla.h
    #ifndef Bla_h
    #define Bla_h
    
    // zeugs
    
    #endif
    
    // in header blubbersuelz.h
    #ifndef Bla_h   <---- durch copy & paste selber include guard noch mal verwendet
    #define Bla_h
    
    // zeugs
    
    #endif

    Wenn in so einem Fall der Compiler in einer Übersetzungseinheit nun zuerst bla.h einzieht, dann kannst du anschließend blubbersuelz.h inkludieren, bis du schwarz wirst; die darin befindlichen Deklarationen / Definitionen wird der Compiler nie sehen, weil für ihn nach dem #ifndef Bla_h Ende Gelände ist.
 

leboh

Ensign
Dabei seit
Mai 2010
Beiträge
167
Zitat von Belchy:
Ich habs jetzt grad eben mal getestet. Wenn ich in User.c "int test;" schreibe, meckert der Compiler nicht, wenn ich die Variable in einer Funktion dort aufrufe.

Wenn ich jetzt jedoch in einer Funktion in IO.c die Variable verändern will, kommt der gleiche Fehler wie vorhin.
Kann das daran liegen, dass User.c nicht in IO.c eingebunden ist? (Ist so vorgegeben).
Wenn ja, muss ich sie dann nicht nochmal definieren?
Ergänzung ()

ich kann eventuell einen kurzen Teil posten, da das Programm an sich nicht mir gehört.

global.h:

#ifndef _GLOBAL_H__
#define _GLOBAL_H__

#if defined(DSPACE)
# include <ipgrt.h>
#endif

#if defined(INTIME) || defined(ARTE_INTIME)
# if defined(__GNUC__)
# include <intime.h>
# endif
#endif

#if !defined(__GNUC__)
# if !defined(__inline__)
# if defined(_MCCPPC)
# define __inline__ inline
# else
# define __inline__ /* nothing */
# endif
# endif
# if !defined(__attribute__)
# define __attribute__(x) /* nothing */
# endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

extern int test;


#ifdef __cplusplus
}
#endif

#endif /* !defined(_GLOBAL_H__) */


user.c

#include <global.h>

int test;

void calc(){
test++;
}

io.c
sieht im prinzip genauso aus wie user.c, nur mit anderen funktionen


wenn in user.c global.h included wird,
und io.c und user.c zusammen gelinkt werden, dann muss das gehen...
 

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Zitat von Belchy:
global.h:

#ifndef _GLOBAL_H__
#define _GLOBAL_H__

Das ist schon mal nicht so toll, da der Standard globale Bezeichner, die mit einem Unterstrich beginnen, für Compilerhersteller reserviert. Wenn du Pech hast, ist dieses Symbol bereits irgend wie definiert. Ich würde dir empfehlen, den führenden Unterstrich wegzuschmeissen. Um ganz sicher zu gehen, würde ich sogar noch einen etwas eindeutigeren Namen wählen ... z.B. GLOBAL_HEADER_INCLUDED.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
Ich denke es wird keinem was sagen, aber ich arbeite mit dem Programm CarMaker von IPG.
Dort sind die ganzen beschriebenen C und H Dateien schon mit Grundgerüst (alle notwendigen Funktionen/Variablen) vorhanden.
Um jetzt das ganze etwas zu optimieren oder andere Berechnungen vorzunehmen, kann man die Files natürlich verändern.
Die oben beschriebenen Datein sollten demnach also schon komplett richtig geschrieben sein.

Was mich halt stuzig macht ist, dass in der Global.h, genau an der Stelle wo ich meine test-Var definiert habe, normal /*.....*/ steht. Für mich ein Zeichen, dass genau hier die globalen Variablen definiert werden sollen.

Und es ist auch schon von Haus aus Global.h in allen anderen C-Files inkludiert.

Ob io.c und user.c zusammen gelinkt werden kann ich nicht sagen. Ich nehme es aber an, da es ja ein zusammenhängendes Programm ist.

Edit: Für das CarMaker Programm gibt es einen extra Compiler (Msys).
 
Zuletzt bearbeitet:

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Kannst du mal folgendes probieren? Nur um sicherzustellen, daß du nicht doch eine andere global.h bekommst, als du möchtest. Benennen deine global.h doch mal um und gib ihr einen möglichst eindeutigen Namen. Natürlich mußt du dann die #include-Anweisungen entsprechend ändern. Dann versuche noch mal zu kompilieren.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
wenn ich genau diese Global.h umbenenne (z.b testing.h), bekomm ich beim kompilieren folgende Fehlermeldung:

testing.h No such file or directory.

Ich habe überall global.h mit testing.h ersetzt
 

cx01

Lt. Junior Grade
Dabei seit
Mai 2010
Beiträge
258
Dann ersetz mal die spitzen Klammern durch Anführungszeichen.
Code:
#include <testing.h>
wird zu:
#include "testing.h"
 

antred

Lt. Commander
Dabei seit
Juni 2010
Beiträge
1.288
Aha! Na das scheint doch meine Vermutung zu bestätigen, daß du da die ganze Zeit eine völlig andere global.h eingezogen hast, als du glaubst. Ich möchte wetten, daß irgend wo auf deinem Rechner noch mindestens eine andere global.h liegt, in der weit und breit kein extern int test; steht. :)

Mit welcher Kommandozeile compilierst du eigentlich? Normalerweise kann man dem Compiler mit einer Option wie z.B. -i <Pfad> -i <2. Pfad> ... -i < n. Pfad> angeben, wo er überall nach Headerdateien suchen soll. Du müßtest nun sicherstellen, daß das Verzeichnis, in dem deine global.h liegt, zu den Verzeichnissen zählt, in denen der Compiler sucht.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
Ich habe gerade mal nachgeschaut, und es sind verschiedene Versionen von CarMaker installiert. Deshalb auch 3 Global.h ;)
Ich habe jetzt einfach mal bei allen extern int test; geschrieben. Jedoch ohne Effekt.
(Habe über Suchen meinen PC mal abgesucht)

Also für das Kompilieren benutze ich ein Programm namens Msys. Die erzeugt ein "MakeFile", in welche man den Installationspfad von CarMaker angeben muss (bzw. das Verzeichnis in dem alle Header Files liegen).
Wenn Msys gestartet wurde (ist ein einfaches cmd Fenster), muss ich noch in meiner Projektordner mit den C-Files navigieren und nur noch "make" eingeben.
Anhand des Pfads in "MakeFile" denke ich, dass der Compiler schon die richtige Global.h nehmen müsste.

Wenn ich #include "testing.h" schreibe, kommt als Fehlermeldung: xxx.c: Global.h: No such file or directory
Wunderlich aber, da in der xxx.c die Global.h ersetz wurde, und ich sonst keine andere finden kann...
 
Zuletzt bearbeitet:

cx01

Lt. Junior Grade
Dabei seit
Mai 2010
Beiträge
258
Du änderst Include-Dateien, die garnicht zum aktuellen Projekt gehören? Ich weiß nicht, ob das so eine gute Idee ist.
Eigentlich musst du das "extern int test;" ja garnicht in eine Include-Datei packen. Du könntest es auch einfach direkt in user.c reinschreiben.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
kein sorge....ich hab sie gleich danach zurück geändert ;)

Das ich die Anweisung in User.c schreibe hab ich getestet, und das würde ja an sich auch funktionieren. Jedoch kennt er sie dann in IO.c nicht, wo es auch wichtig wäre, dass ich mit der Variable arbeiten kann.
 

cx01

Lt. Junior Grade
Dabei seit
Mai 2010
Beiträge
258
Ja dann schreib es doch auch noch in IO.c. Ein Include macht ja nichts anderes, als es einfach in alle Dateien einzufügen.
 

Belchy

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Apr. 2011
Beiträge
9
Wird dann dadurch nicht eine neue test Variable erzeugt?
 

cx01

Lt. Junior Grade
Dabei seit
Mai 2010
Beiträge
258
Also du musst genau einmal "int test;" haben und in allen anderen Dateien dann eben "extern int test;".
 
Top