mikrocontroller.net

Forum: Compiler & IDEs Problem mit globaler Variable


Autor: Günther Frings (taraquedo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe gerade versucht meine globalen Variablen in eine cmd.h 
auszulagern. Es geht z.B. um eine Variable vom Typ uint8_t mit der 
Bezeichnung who. Diese wird außerdem in cmd.c von einer Funktion, sagen 
wir be_my_admin(), verändert.

Jetzt habe ich eben schmerzlich erfahren, dass wenn man static in cmd.h 
benutzt die Variable wohl irgendwie zweimal existiert und jede Änderung 
nicht in main.c ankommt. Also habe ich static weggelassen und jetzt 
dreht mir der Compiler durch! Er sagt mir ich hätte who mehrmals 
definiert. Laut Suchfunktion habe ich aber in allen Datei nur ein 
einziges Mal who in Verbindung mit uint8_t geschrieben. Außerdem kommt 
diese Fehlermeldung nicht wie üblich unter "Build" mit rotem Punkt zum 
Vorschein, sondern erst "Message", dass es PRobleme mit der elf-Datei 
gibt.

cmd.o:(.data+0x4): multiple definition of `who'
main.o:(.data+0x0): first defined here

Irgendwas trotteliges steckt im Code drin, denn ich habe versucht den 
Fehler "im kleinen" zu reproduzieren und da lief es. Also so habe ich es 
versucht nachzustellen, aber wie gesagt - das funktioniert so:
// --- main.c ----------------------------
#include "cmd.h"
extern uint8_t who; // mit oder ohne diese Zeile spielt keine Rolle

int main(void)
{
   who = 0;
   be_my_admin();
   return 0;
}
// --- cmd.h -----------------------------
#ifndef CMD_H
#define CMD_H

#include <stdint.h>

#define UID_ADMIN 0xFF

uint8_t who;

void be_my_admin(void);

#endif
// --- cmd.c -----------------------------
#include "cmd.h"

void be_my_admin(void)
{
   who = UID_ADMIN;
   return;
}

Fällt irgendjemanden spontan ein, wo ich suchen muss? Dieser Fehler 
nervt mich ganz besonders, weil vor dem Umpacken alles so schön 
funktionierte.

Grüße!

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

Bewertung
0 lesenswert
nicht lesenswert
Du vertauscht Definition und Deklaration.

In die Headerdatei gehört

  extern uint8_t who;

In genau EIN Sourcefile gehört

  uint8_t who.

Autor: Günther Frings (taraquedo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhh vielen Dank! Da habe ich genau falsch herum gedacht. Dann ist das 
mit dem extern also auch wieder so eine Sache dem Compiler so lange 
ruhig zu stellen und zu sagen "die Variable gibt es irgendwo, die 
Adresse wird dir der Linker sagen". Das macht natürlich alles viel mehr 
Sinn.

Interessanterweise hatte ich jetzt noch gerade herausgefunden, dass 
dieses o.g. Problem nur dann auftritt, wenn ich in cmd.h die Variable 
initialisiere. Sagen wir uint8_t who = UID_NOBODY; schreibe. Ohne, so 
wie oben, funktionierte es. Klar, weil ich im "Miniprogramm" den Header 
nur einmal in main.c eingebunden habe. Aber auch im Miniprogramm läuft 
es dann nicht mehr mit Initialisierung. Das wäre spannend zu wissen, was 
hier der Compiler für einen Unterschied macht.

Aber das Problem konnte ich lösen, vielen Dank!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Günther Frings wrote:
> Interessanterweise hatte ich jetzt noch gerade herausgefunden, dass
> dieses o.g. Problem nur dann auftritt, wenn ich in cmd.h die Variable
> initialisiere. Sagen wir uint8_t who = UID_NOBODY; schreibe. Ohne, so
> wie oben, funktionierte es.

Das Problem ist, dass in C eine Initialisierung immer mit
einer Definition verbunden ist. In dem Moment, wo eine
Initialisierung vorhanden ist, wird das als Definition aufgefasst,
unabhängig davon, ob ein extern davor steht.

Autor: Nico Gams (ockerle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich bin noch anfänger deswegen ist die frage vlt. ein bisschen blöd, 
aber ich habe etwas nicht ganz verstanden.
Ich habe in meiner Header Datei folgendes stehen:

   extern int globalevariable;

dann in einem anderen c file die definition

   int globale variable;

aber ich muss doch auch irgendwo einen Wert zuweisen odernicht? wenn ich 
also in einem 3. c file einen Wert zuweien will kommt die Fehlermeldung 
diese Deklaration hat keine Speicherklasse... was habe ich also falsch 
verstanden?
Ich habe die Header Datei ja immer inkludiert....

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst unterscheiden zwischen einer Zuweisung und einer
Initialisierung. Eine Zuweisung kann beliebig oft erfolgen, aber nur
innerhalb von ausführbarem Code, d.h. nur innerhalb von Funktionen.

Eine Initialisierung erfolgt nur ein einziges Mal direkt beim
Programmstart und ist Bestandteil der Variablendefinition, also bspw.

int globalevariable = 42;

Du hast vermutlich

globalevariable = 42;

irgendwo außerhalb einer Funktion hingeschrieben. Das ist weder eine
Initialisierung noch eine Zuweisung und deswegen ein Fehler.

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.