Forum: Mikrocontroller und Digitale Elektronik Globale Variablen nötig?


von Stefan (Gast)


Lesenswert?

Hallo,

ich habe eine in C erstellte, ich nenne sie mal Regelungs-/ 
Steuerungssoftware in einer Regelung.c Datei, bei der ich eine Funktion 
alle 10ms aus main aufrufe.
In dieser Funktion werden bestimmte Aktionen durch etwa 10 Flags 
gesteuert und Sollwerte durch 5 Variablen für Berechnungen vorgegeben.
Ich möchte diese Flags und Sollwerte durch verschiedene Funktionen aus 
main heraus verändern. Z.B. Set_Geschwindigkeit(100); oder Set_FlagA;

Bisher habe ich deshalb die Flags und Variablen in der Regelung.c Datei 
static global angelegt und Funktionen geschrieben, die diese Flags und 
Variablen verändern können.
Das heißt innerhalb dieser c.Datei sind die Variablen global, aus main 
heraus sind sie aber nicht sichtbar.

Gibt es andere, bessere Möglichkeiten das zu lösen?

Ich überlege die globalen Variablen noch in einer Struktur 
zusammenzufassen. Könnte ich mir die globalen Variablen aber auch 
irgendwie ganz sparen?
Dann müsste ich aber lokale Variablen einer Funktion von außen verändern 
können. Ist das möglich? Die Funktion soll nicht von den anderen 
Funktionen aufgerufen werden, also kann ich ihr auch keine Werte 
(ohnehin viele) übergeben.

Oder müsste ich das Programm von Grund auf anders organisieren damit ich 
solche Sachen vermeide?

Danke und Gruß Stefan
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan schrieb:
> Gibt es andere, bessere Möglichkeiten das zu lösen?

Was hältst Du denn an dem Konzept für schlecht?

Möchtest Du den Code im Modul mehrfach simultan mit anderen 
Parametersätzen nutzen können, oder geht es Dir um irgendein "Prinzip"?
von Stefan (Gast)


Lesenswert?

Es geht mir eigentlich ums Prinzip. Ich bin Student und habe gelernt, 
dass globale Variablen unschön sind.. Teilweise sind sie aber nötig. Nun 
weiß ich nicht ob sie bei mir nötig sind, oder ich unschön programmiert 
habe;-)

Das ganze ist eine Projektarbeit und ich wollte das Programm so 
gestalten, dass eventuell andere Nachfolger einfach meine C-Datei und 
H-Datei einbinden, eine Funktion void Control(void); alle 10ms aufrufen 
damit die Regelung und Steuerung arbeitet und mittels einmaligem Aufruf 
anderer Funktionen z.B. die Geschwindigkeit ändern können ohne der 
Funktion Control(void) jedesmal eine lange Parameterliste zu übergeben, 
was fast die meiste Zeit gar nicht erforderlich ist.
Beantwortet das deine letzte Frage?

Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die 
Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer 
Struktur zu organisieren?
von suzo (Gast)


Lesenswert?

Bei C, anders als bei C++, braucht man globale Variable. Man sollte sie 
aber als "static" kennzeichnen damit sie nur in der einen .c Datei 
gelten.
von Rolf M. (rmagnus)


Lesenswert?

suzo schrieb:
> Bei C, anders als bei C++, braucht man globale Variable.

Was sollte da in C++ anders sein als in C?

Stefan schrieb:
> Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die
> Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer
> Struktur zu organisieren?

Für die Ausführungsgeschwindigkeit nicht, aber für die Übersichtlichkeit 
des Codes.

> Das ganze ist eine Projektarbeit und ich wollte das Programm so
> gestalten, dass eventuell andere Nachfolger einfach meine C-Datei und
> H-Datei einbinden, eine Funktion void Control(void); alle 10ms aufrufen
> damit die Regelung und Steuerung arbeitet und mittels einmaligem Aufruf
> anderer Funktionen z.B. die Geschwindigkeit ändern können ohne der
> Funktion Control(void) jedesmal eine lange Parameterliste zu übergeben,
> was fast die meiste Zeit gar nicht erforderlich ist.

Du kannst auch der Funktion einen einzigen Parameter übergeben, der ein 
Zeiger auf eine Struktur ist, die alle nötigen Werte enthält. Wo diese 
Struktur tatsächlich steht, ist deinem Regler dann egal.
von Stefan (Gast)


Lesenswert?

Danke für die Antworten erstmal.

Rolf Magnus schrieb:
> Du kannst auch der Funktion einen einzigen Parameter übergeben, der ein
> Zeiger auf eine Struktur ist, die alle nötigen Werte enthält. Wo diese
> Struktur tatsächlich steht, ist deinem Regler dann egal.

Wenn ich der Funktion einen Zeiger auf eine Struktur übergebe, müsste 
die Struktur aber innerhalb meiner C-Datei auch wieder global sein, 
damit verschiedene Funktionen die Werte verändern können oder?
Oder wie lege ich die Struktur an und manipuliere dann am Besten die 
Werte in der Struktur?
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stefan schrieb:
> müsste
> die Struktur aber innerhalb meiner C-Datei auch wieder global sein
Überleg dir mal den Unterschied zwischen "Global" und "Sichtbar".
Wenn du eine globale Struktur/Variable anlegst, dann ist die auf jeden 
Fall nur 1 mal und zwar global da. Es kann nur sein, dass sie von einer 
bestimmten Quelldatei aus nicht sichtbar ist. Du darfst aber trotzdem 
nicht ungestraft dort eine zweite andere gleichnamige Struktur/Variable 
anlegen. Der Linker wird dir da dann Probleme machen.

Du wirst also sowas nicht machen können und meinen, du hättest zwei 
verschiedene globale Variable namens h:
main.c
1
   short h;
2
3
   main() { 
4
      ....
5
   }
sub.c
1
   long h;
2
3
   sub() { 
4
      ....
5
   }
von Mark B. (markbrandis)


Lesenswert?

Stefan schrieb:
> Es geht mir eigentlich ums Prinzip. Ich bin Student und habe gelernt,
> dass globale Variablen unschön sind.

Du hast keine globalen Variablen in dem Sinn, dass sie in jedem 
Software-Modul sichtbar wären. Sondern sie sind in einem einzelnen Modul 
"gekapselt", und andere können darauf nur über definierte Schnittstellen 
(Funktionen) zugreifen. Passt doch.
von Karl (Gast)


Lesenswert?

Abgesehen davon: Im Embedded-Bereich ist die Verwendung von globalen 
Variablen durchaus erforderlich und auch üblich. Mehr als 70% aller 
Autos fahren mit Motorsteuerungen mit größtenteils globalen Variablen 
durch die Gegend.
von Ralf G. (ralg)


Lesenswert?

Lothar Miller schrieb:
> Du wirst also sowas nicht machen können und meinen, du hättest zwei
> verschiedene globale Variable namens h:
> main.c
>    short h;
>
>    main() {
>       ....
>    }
> sub.c
>    long h;
>
>    sub() {
>       ....
>    }

Also avr-gcc meint in so einem Fall:
"Build succeeded with 0 Warnings..."
von Daniel V. (danvet)


Lesenswert?

Lothar Miller schrieb:
> Überleg dir mal den Unterschied zwischen "Global" und "Sichtbar".
> Wenn du eine globale Struktur/Variable anlegst, dann ist die auf jeden
> Fall nur 1 mal und zwar global da. Es kann nur sein, dass sie von einer
> bestimmten Quelldatei aus nicht sichtbar ist. Du darfst aber trotzdem
> nicht ungestraft dort eine zweite andere gleichnamige Struktur/Variable
> anlegen. Der Linker wird dir da dann Probleme machen.
>
> Du wirst also sowas nicht machen können und meinen, du hättest zwei
> verschiedene globale Variable namens h:
> main.c
>
1
>    short h;
2
> 
3
>    main() {
4
>       ....
5
>    }
6
>
> sub.c
>
1
>    long h;
2
> 
3
>    sub() {
4
>       ....
5
>    }
6
>

Und so?:
1
   static short h;
2
3
   main() {
4
      ....
5
   }
sub.c
1
   static long h;
2
3
   sub() {
4
      ....
5
   }
von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Stefan schrieb:
>> Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die
>> Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer
>> Struktur zu organisieren?
>
> Für die Ausführungsgeschwindigkeit nicht, aber für die Übersichtlichkeit
> >des Codes.

Es kann durchaus einen Einfluss auf die Ausführungsgeschwindigkeit und 
Codegröße haben wenn man modulglobale Variablen in einer Struktur 
zusammenfasst. Das alles ist aber Compiler- und Systemabhängig.

Grund:
Der Compiler kennt beim Übersetzen des Moduls (der einzelnen C-Datei) 
die Adressen der globalen Variablen nicht. Über diese entscheidet erst 
der Linker. Er muss also für jeden Zugriff eine komplette Adresse in ein 
Register laden. Werden die Variablen aber in eine Struktur 
zusammengefasst so kennt der Compiler den Offset der einzelnen Elemente 
zueinander und muss nur eine Adresse in ein Register laden und kann dann 
mit Offset adressieren.

Matthias
von Stefan (Gast)


Lesenswert?

Lothar Miller schrieb:
> Du wirst also sowas nicht machen können und meinen, du hättest zwei
> verschiedene globale Variable namens h:
> main.c   short h;
>
>    main() {
>       ....
>    }
> sub.c   long h;
>
>    sub() {
>       ....
>    }

Stimmt das geht nicht, weil die Sichtbarkeit wirklich global über alle 
Module ist. Aber ich habe meine globalen Variablen in meinem Modul mit 
static angelegt, vielleicht kam das in meinem 1. Post nicht genug 
heraus. Also sind sie nur in meinem Modul sichtbar, außer ich deklariere 
sie irgendwo anderes mit extern, oder? Vielleicht setze ich die Begriffe 
auch nicht sauber genug oder falsch ein. Bezeichnet man eine in der 
Sichtbarkeit eingeschränkte globale Variable anders?

Also habe ich diesen genannten Fall:

Daniel V. schrieb:
> Und so?:
>    static short h;
>
>    main() {
>       ....
>    }
> sub.c   static long h;
>
>    sub() {
>       ....
>    }

Und wie in diesem letzten Fall müsste ich die Struktur static global in 
meinem Modul anlegen damit mehrere andere Funktionen in diesem Modul 
Werte innerhalb der Struktur verändern können oder?
Wenn das, wie ich es nun verstanden habe, auch als eine Kapselung 
innerhalb eines Moduls bezeichnet werden kann und wohl häufig eingesetzt 
wird, kann ich mich damit zufrieden geben und diese Lösung umsetzen:-)
Ich dachte nur vielleicht gibt es noch andere Möglichkeiten/Konzepte, 
von denen ich bislang noch nichts gehört habe oder habe noch nicht weit 
genug gedacht.
von Stefan (Gast)


Lesenswert?

Danke auch an den Rest und die Erklärung über die Adressierung mit 
Offset. Dann werde ich, wenn nicht noch andere Ideen kommen, das ganze 
wie bisher, zusätzlich noch in einer Struktur organisiert lösen.
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ralf G. schrieb:
> Also avr-gcc meint in so einem Fall:
> "Build succeeded with 0 Warnings..."
Überraschend.
Und noch überraschender, was hier ganz ohne Fehler und Warnung passiert:
main.c
1
char a;
2
char b;
3
long c;
4
char d;
5
6
int main(void)
7
{
8
   while(1)
9
    {
10
        b=a+3;
11
        sub();
12
        a++;
13
    }
14
}
sub.c
1
struct  
2
{
3
  short v2;
4
  short v1;
5
} a;
6
7
long b;
8
char c;
9
char d;
10
11
void sub (void) {
12
  b = a.v1;
13
}

Dis Sicht der Dinge aus dem AVR-Studio-Debugger siehe Screenshots.
Einmal aus Main.c und einmal von Sub.c aus gesehen. Interessant: die 
Adressen. Es wird einfach der Speicherplatz für das jeweils größere 
Element mit gleichem Namen reserviert.
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan schrieb:
> Also sind sie nur in meinem Modul sichtbar, außer ich deklariere
> sie irgendwo anderes mit extern, oder?

Nein, eine in einem Modul als static deklarierte Variable ist auch mit 
"extern"-Deklaration aus einem anderen Modul heraus nicht sichtbar.

Der Linker wird beim "extern"-Zugriff auf so eine Variable 
korrekterweise "undefined symbol" ausgeben.
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Lothar Miller schrieb:
> Und noch überraschender, was hier ganz ohne Fehler und Warnung passiert:

Das ist eine sehr lästige und unappetitliche Eigenschaft des gcc, daß 
der mehrfach definierte globale Symbole übereinanderlegt. Das lässt sich 
mit -no-common auch abschalten (und sollte, wie Dein Beispiel nahelegt, 
auch wirklich tunlichst abgeschaltet werden).
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.