Hallo,
ich habe in meiner main Funktion mehrere Ereignis, die mehere lokale
Variablen der Funktion main zurücksetzen sollen.
Bsp.
1
intmain(void){
2
uint8_tEreignis1
3
uint8_tEreignis2
4
uint8_tEreignis3
5
uint8_tVariable1
6
uint8_tVariable2
7
uint8_tVariable3
8
uint8_tVariable4
9
uint8_tVariable5
10
11
while(1){
12
if(Ereignis1){
13
Variable1=0;
14
Variable2=0;
15
Variable3=0;
16
Variable4=0;
17
Variable5=0;
18
}
19
20
if(Ereignis2){
21
Variable1=0;
22
Variable2=0;
23
Variable3=0;
24
Variable4=0;
25
Variable5=0;
26
}
27
28
if(Ereignis3){
29
Variable1=0;
30
Variable2=0;
31
Variable3=0;
32
Variable4=0;
33
Variable5=0;
34
}
35
}
36
}
Nun hätte ich aber gerne eine Funktion geschrieben, die einfach
aufgerufen wird und alle 5 Variablen zurückgesetzt werden (aufgrund
Übersichtlichkeit und Schreibarbeit).
Die Funktion sähe dann z.B. so aus:
1
voidRuecksetzen(void){
2
Variable1=0;
3
Variable2=0;
4
Variable3=0;
5
Variable4=0;
6
Variable5=0;
7
8
return;
9
}
Nun ist ja aber das Problem, dass die Funktion die Variablen aus main
nicht kennt.
Wir kann man so etwas lösen ohne die Variablen global anzulegen? Geht
das überhaupt?
Eine allgemeine Lösung gibt es nicht.
Wenn die Variablen irgendwas miteinander zu tun haben, legt man sie
besser als Array oder Struct an. Zum Löschen kann man dann memset()
benutzen.
1
memset(my_array,0,sizeof(my_array));
Gegen global spricht eigentlich nichts, es sein denn, sie solllen
schnell sein (in Registern).
Man kann auch den Code so umstellen, daß die gleiche Sache nur an einer
Stelle auftritt:
Sven schrieb:> Wir kann man so etwas lösen ohne die Variablen global anzulegen? Geht> das überhaupt?
Du brauchst sehr dringend ein C-Buch.
Argument Passing an Funktionen und alles was damit zusammenhängt ist
eine grundlegende Basistechnik in der Programmierung.
Karl Heinz Buchegger schrieb:> Argument Passing an Funktionen ist eine grundlegende Basistechnik.
das ist zwar richtig, aber für 5 Variablen würde ich das nicht als
sinnvoll ansehen. Hier ist wirklich die einfachste Lösung die Variablen
global zu machen.
Peter II schrieb:> Karl Heinz Buchegger schrieb:>> Argument Passing an Funktionen ist eine grundlegende Basistechnik.>> das ist zwar richtig, aber für 5 Variablen würde ich das nicht als> sinnvoll ansehen.
Nächste Basistechnik:
Die Variablen haben ja meistens einen sinnvollen Bezug zueinander. Da
stülpt man dann eine struct drüber.
Variablen, die man dauerhaft braucht, lokal in der main-Funktion
anzulegen macht ohnehin nicht viel Sinn. Damit verschleiert man nur den
Speicherverbrauch und erschwert sich, wie man sieht, das Programmieren.
Mach die Variablen modul-global, wenn mehrere Funktionen darauf
zugreifen sollen:
1
staticuint8_tEreignis1;
2
staticuint8_tEreignis2;
3
staticuint8_tEreignis3;
4
staticuint8_tVariable1;
5
staticuint8_tVariable2;
6
staticuint8_tVariable3;
7
staticuint8_tVariable4;
8
staticuint8_tVariable5;
9
10
staticvoidreset_vars(void)
11
{
12
Variable1=0;
13
Variable2=0;
14
Variable3=0;
15
Variable4=0;
16
Variable5=0;
17
}
18
19
intmain(void)
20
{
21
while(1){
22
if(Ereignis1){
23
reset_vars();
24
}
25
if(Ereignis2){
26
reset_vars();
27
}
28
if(Ereignis3){
29
reset_vars();
30
}
31
}
32
}
Wenn es mehrere gleichartige Variablen sind bietet es sich übrigens an,
daraus ein Struct oder Array zu machen statt alle einzeln anzulegen.
Aber der Code ist ja nur ein Beispiel.
Fabian O. schrieb:> int main(void)> {> while(1) {> if (Ereignis1) {> reset_vars();> }> if (Ereignis2) {> reset_vars();> }> if (Ereignis3) {> reset_vars();> }> }> }
Warum kein logisches OR verwenden?
Peter II schrieb:> das ist zwar richtig, aber für 5 Variablen würde ich das nicht als> sinnvoll ansehen. Hier ist wirklich die einfachste Lösung die Variablen> global zu machen.
Die "einfachste" Lösung ist es schon, aber sicher nicht die Beste.
Globale Variable soll man nicht verwenden. Die bringen ordentlich
Probleme mit sich. Für "quick'n'dirty" können sie ab und zu ganz
praktisch sein. Aber warum soll man sich in diesem Fall den Klotz
"globale Variable" an das Bein binden, wenn es doch auch einfach
ordentlich geht?
Progger schrieb:> Aber warum soll man sich in diesem Fall den Klotz> "globale Variable" an das Bein binden, wenn es doch auch einfach> ordentlich geht?
der übergeben von Variabeln kosten auch zeit (bei einem kleinen AVR
durch aus relevent). Außerdem sieht so so gleich den RAM verbraucht.
Damm muss man sich auch noch um das init kümmern, das braucht man bei
globalen auch nicht.
auf einem PC verwende ich auch keine Globalen variablen, auf einem AVR
schon.
Peter II schrieb:> der übergeben von Variabeln kosten auch zeit (bei einem kleinen AVR> durch aus relevent).
Es kommt immer drauf an, wieviele Argumente man hat, welche Datentypen
involviert sind, wie oft die Funktion aufgerufen wird, wie zeitkritisch
das ganze ist, ....
> auf einem PC verwende ich auch keine Globalen variablen, auf einem AVR> schon.
Yep. Auf einem AVR muss man schon mal die Krot aus praktischen Gründen
schlucken.
Nichtsdestotrotz MUSS der TO lernen, wie Argument Passing funktioniert.
Denn für alles und jedes globale Variablen zu machen, ist dann ebenfalls
der falsche Ansatz
jack schrieb:> ich würd jetzt gerne einen blöden Kommentar schreiben, von wegen C-Buch> und Stringzuweisung
Die "Stringzuweisung" wäre in Ordnung, sofern global_arg_to_puts als
char* definiert ist. Die puts-Funktion würde allerdings nicht
funktionieren ... ;-)
Man sollte übrigens deutlich zwischen globalen Variablen (ohne static)
und Modulvariablen (mit static) unterscheiden. Letztere sind kein
Teufelszeug und wird man in jedem realen, vernünftig geschriebenen
C-Programm brauchen, egal ob µC oder PC.
Fabian O. schrieb:> Letztere sind kein> Teufelszeug und wird man in jedem realen, vernünftig geschriebenen> C-Programm brauchen, egal ob µC oder PC.
doch sind sie, spätestens wenn man mit Threads anfängt merkt man das
globale (egal welche) nicht wirklich gut sind.
Fabian O. schrieb:> Wo speicherst Du denn stattdessen die Daten?
was für daten? z.b. in stucts.
struct Moduldaten md;
ModulInit( &md );
ModulMachWas( &md, "was soll ich machen?" );
ModulClose( &md );
Fabian O. schrieb:> Oder legst Du die in der main-Funktion
ja
> auf dem Stack an? Oder mit malloc?
ist egal
> Wenn ja, was soll daran besser sein?
ich kann das Modul mehrfach gleichzeig z.b. in Thread nutzen.
Peter II schrieb:> ich kann das Modul mehrfach gleichzeig z.b. in Thread nutzen.
Das hat ja nichts damit zu tun, wo Du die Variable anlegst. Du machst
also folgendes:
1
intmain(void)
2
{
3
structModuldatenmd;
4
5
ModulInit(&md);
6
ModulMachWas(&md,"was soll ich machen?");
7
ModulClose(&md);
8
}
Mein Frage ist, warum nicht so?
1
staticstructModuldatenmd;
2
3
intmain(void)
4
{
5
ModulInit(&md);
6
ModulMachWas(&md,"was soll ich machen?");
7
ModulClose(&md);
8
}
Vorteil:
- Der Compiler kann den Speicherverbrauch ermitteln.
- Die Daten belegen keinen Platz auf dem Stack (gerade am PC relevant,
wenn die Struktur groß ist und der Stack begrenzt).
- Du kannst ModulMachWas() auch von anderen Funktionen in main.c aus
aufrufen, ohne dass der Funktion &md übergeben werden muss (darum ging
es ja im Prinzip im Ausgangspost).
Nachteil:
- Mir fällt keiner ein?
Fabian O. schrieb:> Nachteil:> - Mir fällt keiner ein?
so wie du es jetzt gemacht hast es es ja ok, wenn aber das
static struct Moduldaten md;
in der Modul.c datei steht, dann wird es blöd.
Das ist ein anderes Thema, nämlich ob man von dem Modul mehrere
Instanzen braucht oder nicht. Wenn man garantiert nur eine Instanz davon
hat/braucht, dann kann man sich das Übergeben des Zeigers auf die Daten
bei jedem Funktionsaufruf sparen. Bei Mikrocontrollern ist das meiner
Erfahrung nach meistens der Fall ...
In Anwendungen, bei denen man mit mehreren Modulen mit mehrfachen
Instanzen zu tun hat, fährt man wahrscheinlich mit C++ besser, denn da
ist die Objektorientierung gleich eingebaut.