mikrocontroller.net

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


Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?!

Autor: Jürgen Fitschen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

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

volatile char tmp_var[8];


Viel Erfolg,
Jürgen Fitschen

Autor: schmichi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

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

Gruß Michael

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
versuchs mal mit static

static tmp_var[8];

Autor: Anfänger (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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! ;-)

Autor: Thomas Kropf (thomas_k)
Datum:

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

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
huch. Hab das reloaden vorher vergessen :(

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas Kropf (thomas_k)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-fno-common

Autor: Thomas Kropf (thomas_k)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg Wunsch:
Sehr interessant. Danke!

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

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau Sichtbarkeiten  .. danke :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.