Forum: Mikrocontroller und Digitale Elektronik Parameter in Funktion speichern. Geht das überhaupt? C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Attila C. (attila)


Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich möchte innerhalb einer main Schleife eine Funktion A aufrufen und 
dieser 3 Werte übergeben, z.b. mit Schiebereglern.

Wenn jetzt bei Funkion A alles geregelt ist möchte ich 3 Parameter einer 
Funktion B übergeben, mit den gleichen Schiebereglern.

Wie schaffe ich es dass Funktion A sich die letzten Werte "merkt" ohne 
dass die Werte überschrieben werden?

Wahrscheinlich ist es ganz einfach und ich stehe nur grade auf dem 
Schlauch. :-(

Danke für Hinweise!

von Fabian (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Leider ist deine Frage nicht klar. Wenn Funktion A durch ist, wird diese 
verlassen und danach Funktion B aufgerufen. Wie kommt Funktion A ist 
wieder ins Spiel?!

von PTx (Gast)


Bewertung
2 lesenswert
nicht lesenswert
ein "static" vor die Variablen in A() schreiben.

von Attila C. (attila)


Bewertung
0 lesenswert
nicht lesenswert
Beide Funktionen werden dauernd aufgerufen! Durch einen Schalter z.B. 
könnte bestimmt werden für welche der Funktionen die Schieberegler grade 
gültig sind.

Ein static löst das Problem nicht da ja die Schieberegler weiter 
betätigt werden.

von Guest (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mir ist leider nicht klar, was es mit deinen Schiebereglern auf sich hat 
aber in C hast du drei Möglichkeiten:

1. Globale Variable
1
int hugo = 42;
2
3
void foo(void) {
4
  hugo++;
5
}
6
7
void bar(void) {
8
  hugo--;
9
}
10
11
int main(void) {
12
  hugo = 0;
13
  foo();
14
  bar();
15
}

2. Pass by value
1
void foo(int a) {
2
  a++;
3
}
4
5
int main(void) {
6
 int hugo; 
7
 hugo = 0;
8
 foo(hugo);
9
  // hugo is still zero
10
}


3. Pass by reference
1
void foo(int* a) {
2
  *a++;
3
}
4
5
int main(void) {
6
 int hugo; 
7
 hugo = 0;
8
 foo(&hugo);
9
  // hugo is now 1
10
}

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Deine Beschreibung bleibt unklar.

von Attila C. (attila)


Bewertung
-1 lesenswert
nicht lesenswert
Also:

1) Frage die Schieberegler ab.
2) Schreibe die Werte der Schieberegler in Funktion A solange bis:
3) Funktion B aktiv ist.Dann führe Funktion A mit den letzten 
übergebenen Parametern weiter aus.
4) Schreibe demnach die Werte der Schieberegler in Funktion B solange 
bis:
5) Funktion C aktiv ist. Dann führe Funktion A mit seinen 
(gespeicherten?) Parametern aus und führe B mit den letzten übergebenen 
Parametern weiter aus.
6) Schreibe demnach die Werte der Schieberegler in Funktion C.
...usw.....
7) Fang von vorne an.

von Ralf G. (ralg)


Bewertung
0 lesenswert
nicht lesenswert
Attila C. schrieb:
> Also:
Vielleicht ist dein Ansatz nicht der Richtige.

Ich habe das jetzt so verstanden:
Auf Grund eines bestimmten Ereignisses (Zeit abgelaufen, 10 Durchläufe, 
...)
sollen die Eingabeparameter mit einer weiteren/ der nächsten Funktion 
verarbeitet werden.

Da könnte man jeder Funktion zusätzlich ein Flag oder eine 
Statusvariable übergeben, welche(s) anzeigt, dass eine weitere Funktion 
aktiv ist und somit mit den letzten Werten weitergerechnet werden soll. 
'static' ist hier trotzdem nötig.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Indem Du zu den 3 noch einen vierten Parameter mitgibst, ob die 3 für 
Funktion A oder B gelten.

Alternativ die Parameter auf einen "Spezial-Wert" setzen. Z.B. -1 wenn 
sonst nur 0..100 gültig sind.

Und lokale Spiegel der Variablen ("static"), damit die letzten Werte 
gültig bleiben.
1
void FuncA(int X, int Y, int Z, int BoxChecked)
2
{
3
static int p[3];
4
5
   /* hier nur, wenn BoxChecked == 0, in B andersrum*/
6
   if(!BoxChecked)
7
   {
8
      p[0]=X;
9
      p[1]=Y;
10
      p[2]=Z
11
   }
12
   ... und hier nur noch p[0..2] verwenden
13
}

von Stefan K. (stefan64)


Bewertung
-1 lesenswert
nicht lesenswert
Hier mein Vorschlag ohne static. Hat den Vorteil, dass Du ggf. 
verschiedene Functionen wiederverwenden kannst, wenn dort eigentlich 
dasselbe passiert.
1
typedef struct
2
{
3
  int p1;
4
  int p2;
5
  int p3;
6
} paramsTypeDef;
7
8
enum actualFunctionEnum
9
{
10
  isFunctionA = 0,
11
  isFunctionB,
12
  isFunctionC,
13
  isNoFunction,
14
}
15
16
17
void functionA (paramsTypeDef *pSavedparameters, *pActualParameters, int saveMyParams)
18
{
19
  // do code of A
20
21
  if (saveMyParams)
22
  {
23
    memcpy (pSavedparameters, pActualParameters, sizeof(paramsTypeDef));
24
  }
25
}
26
27
28
void functionBC (paramsTypeDef *pSavedparameters, *pActualParameters, int saveMyParams)
29
{
30
  // do code of B and C
31
32
  if (saveMyParams)
33
  {
34
    memcpy (pSavedparameters, pActualParameters, sizeof(paramsTypeDef));
35
  }
36
}
37
38
39
void main()
40
{
41
  paramsTypeDef paramsA;
42
  paramsTypeDef paramsB;
43
  paramsTypeDef paramsC;
44
  paramsTypeDef actualFaders;
45
  actualFunctionTypeDef actualFunction = isFunctionA;  
46
  int saveParams;
47
48
  while(1)
49
  {
50
    getfader(&actualFaders);
51
    saveParams = shouldISaveParams();
52
 
53
    switch (actualFunction)
54
    {
55
      case isFunctionA:
56
        functionA(&paramsA, &actualFaders, saveParams);
57
        if (saveParams) actualFunction = isFunctionB;
58
        break;
59
60
      case isFunctionB:
61
        functionB(&paramB, &actualFaders, saveParams);
62
        if (saveParams) actualFunction = isFunctionC;
63
        break;
64
65
      case isFunctionC:
66
        functionC(&paramsC, &actualFaders, saveParams);
67
        if (saveParams) actualFunction = isNoFunction;
68
        break;
69
70
      case isNoFunction:
71
        if (saveParams) actualFunction = isFunctionA;
72
        break;
73
74
      default:
75
        actualFunction = isFunctionA;  // you should never get here!
76
        break;
77
    } 
78
  }    // end of while(1)
79
}      // end of main()
Ich würde ggf. noch das Ändern der Parameter und das Processing 
voneinandern trennen (nicht oben implementiert).

Z.B.:
void changeParams (paramsTypeDef *pSavedparameters, *pActualParameters, 
int saveMyParams)
void processA/B/C(paramsTypeDef *pSavedparameters);

Für das Ändern der Parameter brauchst Du dann nur eine Function, weil 
die bei A,B,C exakt dasselbe tut.

Gruß, Stefan

von Axel S. (a-za-z0-9)


Bewertung
-1 lesenswert
nicht lesenswert
Attila C. schrieb:

> Ich möchte innerhalb einer main Schleife eine Funktion A aufrufen und
> dieser 3 Werte übergeben, z.b. mit Schiebereglern.

Dunkel der Sinn deiner Rede ist. Schieberegler sind kein Konzept der 
Programmiersprache C. Variablen hingegen sind es. Und Werte, die man 
an Funktionen übergibt, nennt man in C (und nicht nur da) üblicherweise 
Funktionsparameter. Ach ja: "main Schleifen" gibt es in C auch nicht.

> Wenn jetzt bei Funkion A alles geregelt ist möchte ich 3 Parameter einer
> Funktion B übergeben, mit den gleichen Schiebereglern.

Wenn du zwei Funktionen mit den gleichen Parametern aufrufen willst, 
dann mach das doch einfach.

> Wie schaffe ich es dass Funktion A sich die letzten Werte "merkt" ohne
> dass die Werte überschrieben werden?

Wenn Funktion A so definiert ist, daß sie drei Parameter erwartet, dann 
werden diese Parameter aus Sicht der Funktion immer überschrieben. 
Aber der Aufrufer der Funktion hat ja volle Kontrolle darüber, wie er 
die Funktion aufruft. Wenn er zweimal die gleichen Parameter verwenden 
will, dann kann er das selbstverständlich tun.

> Wahrscheinlich ist es ganz einfach und ich stehe nur grade auf dem
> Schlauch. :-(

Davon ist auszugehen. So wie es sich mir darstellt, hast du noch nicht 
mal die Aufgabe verstanden.

von A. S. (achs)


Bewertung
1 lesenswert
nicht lesenswert
Stefan K. schrieb:
> Hier mein Vorschlag ohne static. Hat den Vorteil, dass Du ggf.
> verschiedene Functionen wiederverwenden kannst, wenn dort eigentlich
> dasselbe passiert.

Ist das jetzt Satire, oder willst Du dem TO wirklich helfen?

Und für uns, könntest Du nochmal den Vorteil beschreiben, den der 
NV-Speicher auf dem Stack gegenüber static hat?

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Du mußt Dir zuerst mal ein Bedienkonzept überlegen. Also wie die 
Funktionen A,B,C ausgewählt werden und wann die Schieberegler übernommen 
werden sollen.
Einfach so drauflos programmieren führt zu nichts.

Auch könnte es das Verständnis wesentlich erhöhen, wenn Du sagst, was 
A,B,C konkret machen sollen. Abstrakte Fragestellungen helfen nur selten 
weiter, mit Gedankenlesen tun sich hier viele schwer.

von Der Andere (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Du solltest dir ein gutes C Buch besorgen und es durcharbeiten.
Werte speichert man in Variablen.
Funktionen dienen nur dazu irgendwas auszuführen, dazu brauchen sie oft 
Variablen und manipulieren sie, aber Funktionen "bewahren" im 
Allgemeinen keine Variablen auf.

von Arduino Fanboy D. (ufuf)


Bewertung
1 lesenswert
nicht lesenswert
Der Andere schrieb:
> Funktionen dienen nur dazu irgendwas auszuführen, dazu brauchen sie oft
> Variablen und manipulieren sie, aber Funktionen "bewahren" im
> Allgemeinen keine Variablen auf.

So ist es.

In manchen Situationen vereinfachen lokale statische Variablen das 
Leben.

Allerdings:
Funktionen sollten ein reproduzierbares Verhalten zeigen. Also bei 
gleichen Parametern, immer das selbe Ergebnis bringen. Das macht sie 
leichter testbar und auch wiederverwendbar.

Wenn sie lokale statische Variablen beinhalten, kann das bei unachtsamer 
Verwendung zu unerwünschten Seiteneffekten führen.

Das wollen wir doch nicht!
Oder?

Einerseits ist das ein erlaubtes Sprachmittel, aber andererseits gilt 
auch der Spruch: "Wer einmal begriffen hat, wie ein Hammer funktioniert, 
für den sieht jedes Problem wie ein Nagel aus"

von Stefan K. (stefan64)


Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> Ist das jetzt Satire, oder willst Du dem TO wirklich helfen?

Wenn ich das nicht ernst meinen würde, hätte ich mir wohl kaum die Mühe 
gemacht.

> Und für uns, könntest Du nochmal den Vorteil beschreiben, den der
> NV-Speicher auf dem Stack gegenüber static hat?

* Bei static kannst Du die Werte nur innerhalb dieser Funktion benutzen.
  Meistens ist es aber sinnvoll, solche Parameter an mehreren Stellen
  verfügbar zu haben. Das kan static nicht leisten.

* Bei static kann die Funktion nur einmal mit genau diesen Parametern
  verwendet werden. Wiederverwendbarkeit ist damit ausgeschlossen.
  Das Problem des TO sieht aber danach aus, dass seine Schieberegler auf
  genau dieselbe Weise in 3 Funktionen in unterschiedliche Parameter
  gesichert werden.

Ob die Parameter A/B/C global oder in main() definiert werden, ist 
dagegen erstmal zweitrangig.

In C++ liesse sich das Ganze übrigens noch deutlich eleganter lösen.

Gruß, Stefan

: Bearbeitet durch User
von Attila C. (attila)


Bewertung
1 lesenswert
nicht lesenswert
Erst mal an alle: Vielen Dank!

Ralf G. Und Achim S. : Genau danach hatte ich gesucht! Danke!

Stefan K. : Danke, aber die Werte müssen nicht weiter verändert werden.

Axel Schwenke: Das ich eine Aufgabe die meinen eigenen Überlegungen 
entspringt nicht verstanden haben soll ist an Absurdität kaum zu 
überbieten!

Peter Danneger: Ich habe den wahren Zweck der Anwendung nicht 
beschrieben um mich nicht dem allseits beliebten Bashing in diesem Forum 
auszusetzen. Dieser Thread wäre, wie leider so viele hier, komplett 
off-topic gegangen! Ansonsten ist es ,wie so oft, wie mit dem 
Schuhe-zubinden: Es ist gar nicht so einfach zu beschreiben.

Der Andere: Die von Ralf und Achim vorgeschlagene Idee ist sicher nicht 
in einem C-Buch zu finden.

Noch einmal vielen Dank!

von Ralf G. (ralg)


Bewertung
0 lesenswert
nicht lesenswert
@ Attila C.
Mal noch ein später Hinweis:
Arduino F. schrieb:
> Allerdings:
> Funktionen sollten ein reproduzierbares Verhalten zeigen. Also bei
> gleichen Parametern, immer das selbe Ergebnis bringen.

Auch ich würde die berechneten Werte außerhalb der Funktion speichern 
und die Funktion, wenn die Werte nicht verändert werden sollen, gar 
nicht erst aufrufen.

Arduino F. schrieb:
> Das macht sie leichter testbar und auch wiederverwendbar.

Eventuell kann man dann Teile der Funktionen A, B, C, ... sogar noch 
zusammenfassen.

: Bearbeitet durch User
von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Stefan K. schrieb:
> memcpy (pSavedparameters, pActualParameters, sizeof(paramsTypeDef));

wieso nicht
1
*pSavedParameters = *pActualParameters;
?? Das reduziert (mindestens) eine Fehlerquelle und erlaubt dem 
Compiler, so zu optimieren, wie er das für richtig hält (wenn auch in 
vielen Fällen dasselbe rauskommt).

Es ist schon sehr lange her, dass C keine struct-Zuweisungen 
k[a,o]nnte.

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]
  • [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.