Forum: Compiler & IDEs Globale Variable in Funktion nicht erkannt?!


von Anfänger (Gast)


Lesenswert?

Ich habe in meiner main.c ganz zu beginn eine variable definiert (also
global).

char tmp_var[8];

Nun schreit der Compiler, wenn eine andere Funktion mit diesen Werten
arbeiten will:

error: `tmp_var' undeclared (first use in this function)

Wenn ich in der Funktion die variable nochmal definiere, gleich wie zu
Beginn, dann passts ihm.

Meine Frage ist warum?

Wenn in der erten Zeile des main programmes die Variable definiert
wird, warum ist die dann in einer anderen Funktion undeklariert?!

von Jürgen Fitschen (Gast)


Lesenswert?

Hi!

Wenn ich mich nicht irre, musst du das Array als volatile definieren:

volatile char tmp_var[8];


Viel Erfolg,
Jürgen Fitschen

von schmichi (Gast)


Lesenswert?

Hi,

Poste mal ein wenig Code, damit man dir helfen kann. So ist das ein
wenig dürftig.

Gruß Michael

von Simon K. (simon) Benutzerseite


Lesenswert?

versuchs mal mit static

static tmp_var[8];

von Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

Habe das WinAVR Project im Anhang.

Das Programm sollte jede Sekunde den aktuellen ADC Wert per UART
verschicken..... die drm3310 display dateien könnt ihr im Moment
vergessen, komemn erst später hinzu...


Wie gesagt, wenn ich in der Funktion adc_ergebnis() nicht nochmal die
zwei variablen buf_quo[8] und  buf_rem[8] definiere, gibt das
kompilieren einen error....

Aber seht selbst ;-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die globalen Variablen dürfen nicht als "static"
deklariert/definiert werden - sonst sind sie nämlich eben NICHT
global.

Sie dürfen nur in einem Sourcefile definiert werden, damit aber
Funktionen aus anderen Sourcefiles auf sie zugreifen können, muss für
diese anderen Sourcefiles die Deklaration der Variablen bekannt gemacht
werden. Das geschieht mit einer "extern"-Deklaration in einer
Headerdatei.
In jedem Sourcefile, in dem auf diese globalen Variablen zugegriffen
werden soll, muss die Headerdatei mit der Deklaration eingebunden
werden.

Beispiel:


  // headerdatei "main.h"
  extern char buf_quo[8];  // Deklaration


  // main.c
  char buf_quo[8];  // Definition. Initialisierung
                    // muss hier erfolgen, wenn benötigt


  // blafusel.c
  #include "main.h"  // liest Deklaration


So eine "extern"-Deklaration teilt dem Compiler analog zum
Funktionsprototypen mit, daß es eine Variable des betreffenden Namens
und Typs gibt, so daß der Compiler das betreffende Quellfile ohne
Fehlermeldung übersetzen kann.

Es empfiehlt sich, globale Variablen (wenn man sie denn unbedingt
benutzen muss) in eine eigene Quelltextdatei zu packen, und eine
Headerdatei gleichen Namens anzulegen, in der die Variablen deklariert
werden. Naheliegend ist hier "globals.c/globals.h", da weiß man, was
man hat.


Als "volatile" müssen Variablen nur dann deklariert werden, wenn sie
am Optimizer des Compilers vorbei geändert werden können, was in
Interruptroutinen etc. geschehen kann, das aber hat nichts mit dem hier
vorliegenden Problem zu tun.

von Anfänger (Gast)


Lesenswert?

Ach so ist das! Jetzt kapier ich endlich, wie das ist mit dem
"extern"

Danke für das super Beispiel!Leuchtet mir jetzt ein! ;-)

von Thomas K. (thomas_k)


Lesenswert?

Probier mal
extern char buf_quo[8];
in adc.c oder mach eine gemeinsame .h Datei wo char buf_quo[8]
drinsteht.

von Thomas K. (thomas_k)


Lesenswert?

huch. Hab das reloaden vorher vergessen :(

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

@Thomas:
Genau andersrum. In die Headerdatei gehört die Deklaration, nicht die
Definition der Variablen.

Wenn man die Definition der Variablen in die Headerdatei packt, dann
wird für jedes einzelne Sourcefile im Projekt, das diese Headerdatei
einbindet, eine neue globale Variable angelegt ... was dann vollkommen
zu recht der Linker moniert.

gcc bietet eine Option, dies zuzulassen und die Kopien quasi
aufeinander abzubilden, das aber ist nicht standardkonform und meiner
Ansicht nach übler Murks.

von Thomas K. (thomas_k)


Lesenswert?

Ja, du hast wohl recht. Obwohl ich dieses "Kopieren" der globalen
Variable nicht entdecken kann.

Allerdings wäre das "extern char buf_quo[8];" in adc.c doch trotzdem
richtig wenn in main.c "char buf_quo[8];" steht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das "kopieren" geschieht, wenn folgendes

  char globale_variable;

in einer Headerdatei steht, die in mehrern Sourcefiles eines Projektes
eingebunden wird.

Das hast Du so vorgeschlagen:

   oder mach eine gemeinsame .h Datei wo
   char buf_quo[8] drinsteht.


Davon abgesehen ist es natürlich auch möglich, die extern-Deklaration
nicht in die Headerdatei, sondern in jedes Sourcefile zu schreiben, in
dem man sie benötigt. Muss ich wirklich darauf hinweisen, daß so eine
Vorgehensweise ausgemachter Murks ist?

von Thomas K. (thomas_k)


Lesenswert?

Ich habe doch gesagt, dass du recht hast. Allerdings merke ich nichts
von diesem "Kopier"-Effekt. Hab es gerade getestet (Im Endeffekt ist
das nochmal mein Posting von vorhin).

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du den "Kopier"-Effekt nicht feststellen kannst (also Dein Linker
nicht über mehrfach definierte Symbole klagt), dann verwendest Du gcc in
eben jenem nicht standardkonformen Modus, der klaglos Symbol-Doubletten
zusammenfasst. Ich vermag Dir aber nicht zu sagen, wie exakt die dafür
verantwortliche Kommandozeilenoption lautet; tut mir leid.

von Thomas K. (thomas_k)


Lesenswert?

Also ich seh da jetzt nichts besonderes dran:
gcc -ansi -pedantic -Wall -g main.c func.c -o main
aber egal

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

-fno-common

von Thomas K. (thomas_k)


Lesenswert?

Achso, es ist umgekehrt. Man braucht diesen Parameter damit er den
Fehler anzeigt. Sehr interessant. Wieder was gelernt :)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Man braucht diesen Parameter damit er den
> Fehler anzeigt.

Ja, der default von GCC ist, .bss-Variablen (nicht initialisierte
globale Variablen) in sogenannte Common-Blöcken anzulegen.  Dieses
Linker-Feature stammt von FORTRAN und gestattete es dort,
Datenbereiche aus verschiedenen Moduln im Linker überlagern zu lassen.

Ich vermute mal, dass das Ur-C von K&R das Wort "extern" einfach
noch
nicht besass.  Dadurch sahen die Deklaration und die Definition einer
nicht initialisierten Variablen identisch aus.  Durch die Benutzung
eines Common-Bereichs wurden dann alle gleichnamigen globalen
Variablen durch den Linker auf einen einzigen Speicherbereich
abgebildet.  Später blieb die daraus resultierende Schlampigkeit,
Deklarationen und Defininitionen nicht sauber zu trennen, in der
Unix-Welt dann noch lange erhalten (weil das einfach in alten
Quelltexten usus war), sodass die Compiler das nach wie vor so
implementieren.

von Ulli (Gast)


Lesenswert?

Hallo

komisch, dass bei dem Compiler, den ich hier verwende (CAVR) und auch
in diversen Büchern steht (in dem Ansi C erklärt wird) , dass -static-
sehr wohl auch global sein kann - vorausgesetzt es -nicht!- in einer
Funktion deklariert wird und es sich nur auf diese Datei bezieht, in
der es steht. Darüber hinaus werden mit static deklarierierte Variablen
immer mit 0, vom Compiler initialisiert und von dem irgendwie auch
speziell optimiert.
Extern hingegen sollte sich, soweit ich weiß, eben noch "mehr"
global, für mehrere Dateien sein, die auf dieselbe Variable zugreifen.

Nun zum Problem: (was bei CAVR genauso auftritt)
Variablen die ohne diese Parameter deklariert sind, müssen auf jeden
Fall -vor den Funktionen stehen, die sie verwenden und das geschieht
normal am Datei Anfang.

mfg Ulli

von Thomas K. (thomas_k)


Lesenswert?

@Jörg Wunsch:
Sehr interessant. Danke!

@Ulli:
Ich glaub die Worte die du suchst sind "File Scope" bzw. "Gobal
Scope":)

von Ulli (Gast)


Lesenswert?

genau Sichtbarkeiten  .. danke :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.