Code in Funktion zusammenfassen

Gast #2991355
Lesenswert?

Hallo,

ich habe in meiner main Funktion mehrere Ereignis, die mehere lokale 
Variablen der Funktion main zurücksetzen sollen.

Bsp.
1
int main(void){
2
uint8_t Ereignis1
3
uint8_t Ereignis2
4
uint8_t Ereignis3
5
uint8_t Variable1
6
uint8_t Variable2
7
uint8_t Variable3
8
uint8_t Variable4
9
uint8_t Variable5
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
void Ruecksetzen (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?
#2991429
Lesenswert?

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:
1
int main(void){
2
uint8_t Ereignis1
3
uint8_t Ereignis2
4
uint8_t Ereignis3
5
uint8_t Variable1
6
uint8_t Variable2
7
uint8_t Variable3
8
uint8_t Variable4
9
uint8_t Variable5
10

11
  while(1){
12
    Variable1=0;
13
    Variable2=0;
14
    Variable3=0;
15
    Variable4=0;
16
    Variable5=0;
17
    while(1){
18
     if (Ereignis1)
19
       break;
20
     if (Ereignis2)
21
       break;
22
     if (Ereignis3)
23
       break;
24
     if (Ereignis4)
25
       break;
26
    }
27
  }
28
}

Peter
#2991521
Lesenswert?

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.

1
void foo( int* i)
2
{
3
  *i = 5;
4
}
5

6
int main()
7
{
8
  int j = 8;
9

10
  // j hat den Wert 8
11

12
  foo( &j );
13

14
  // jetzt hat j den Wert 5. foo hat ihn gesetzt
15
}
#2991689
Lesenswert?

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
static uint8_t Ereignis1;
2
static uint8_t Ereignis2;
3
static uint8_t Ereignis3;
4
static uint8_t Variable1;
5
static uint8_t Variable2;
6
static uint8_t Variable3;
7
static uint8_t Variable4;
8
static uint8_t Variable5;
9

10
static void reset_vars(void)
11
{
12
  Variable1 = 0;
13
  Variable2 = 0;
14
  Variable3 = 0;
15
  Variable4 = 0;
16
  Variable5 = 0;
17
}
18

19
int main(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.
Gast #2991888
Lesenswert?

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?
Gast #2991893
Lesenswert?

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.
#2991987
Lesenswert?

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
1
void puts()
2
{
3
  while( global_arg_to_puts )
4
  {
5
    global_arg_to_putc = *s++;
6
    putc();
7
  }
8
}
9

10

11
int main()
12
{
13
  ....
14

15
  global_arg_to_puts = "Hallo world";
16
  puts();
17

18
  global_arg_to_puts = "Juhu";
19
  puts();
20

21
  sprintf( buffer, "%d", i );
22
  global_arg_to_puts = buffer;
23
  puts();

das kanns ja offensichtlich nicht sein.
#2992153
Lesenswert?

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.
#2992230
Lesenswert?

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
int main(void)
2
{
3
  struct Moduldaten md;
4

5
  ModulInit( &md );
6
  ModulMachWas( &md, "was soll ich machen?" );
7
  ModulClose( &md );
8
}

Mein Frage ist, warum nicht so?
1
static struct Moduldaten md;
2

3
int main(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?
#2992239
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren