Fragen zu Header Dateien

Belchy

Cadet 1st Year
Registriert
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
 
Du bist 100%-ig sicher, daß du den Header in User.c auch wirklich inkludierst?
 
in User.c fehlt ein
int test;

extern int ist eine Deklaration, was noch fehlt ist eine Definition. Eine.
 
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:
leboh schrieb:
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.

Belchy schrieb:
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 ()

Belchy schrieb:
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:
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:
Belchy schrieb:
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.
 
Belchy schrieb:
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...
 
Belchy schrieb:
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.
 
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:
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.
 
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
 
Dann ersetz mal die spitzen Klammern durch Anführungszeichen.
Code:
#include <testing.h>
wird zu:
#include "testing.h"
 
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.
 
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:
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.
 
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.
 
Ja dann schreib es doch auch noch in IO.c. Ein Include macht ja nichts anderes, als es einfach in alle Dateien einzufügen.
 
Wird dann dadurch nicht eine neue test Variable erzeugt?
 
Also du musst genau einmal "int test;" haben und in allen anderen Dateien dann eben "extern int test;".
 
Zurück
Oben