mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ZeigerArray auf Funktionen nachträglich als ganzes umschreiben


Autor: S. Hager (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe eine Frage zu Funktionszeigern:
Das initialisieren am Anfang klappt gut, ich kann alle Funktionen in das 
Array schreiben. Will ich aber zur Laufzeit alle Funktionen im Array 
ändern, so kann ich es nur einzeln machen und nicht gemeinsam in 
geschwungener Klammer.



typedef void keyfunction(void);

void set1(void);
void set2(void);

keyfunction *key_call[MAXKEYS]={ set1, set2};  // hier geht es



Wenn ich aber zur Laufzeit das machen möchte spinnt der Compiler rum und 
ich hab keine Ahnung warum:

void main(){
...

key_call = {set2, set1}; // A: das lässt mir der Compiler so nicht 
durchgehen

key_call[0] = set2; // B: das jedoch schon
key_call[1] = set1; // B: und das somit auch


wenn ich aber viel zum uminitialiseren habe wird das so langweilig und 
es ist nicht so elegant. Geht A überhaupt zur Laufzeit?

Weder in der Literatur noch in google konnt ich eine Antwort darauf 
finden, ich würde mich freuen wenn mir jemand weiterhelfen könnte.

Autor: gast854 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
a geht nicht zur laufzeit, ist einfach so.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Initialisieren mit {} geht nur beim Initialisieren, daher der Name.
Eine spätere Zuweisung geht wie gesagt nicht mit {}.

Falls du aber die Zuweisungen nicht vollkommen willkürlich durcheinander
machen musst, sondern beispielsweise zwischen einigen wenigen, vorher
bekannten Konfigurationen umschalten willst, kannst du dir diese
Konfigurationen in je einem Feld von Zeigern ablegen.
Zum Umschalten gibt es dann zwei Möglichkeiten:
- in dein eigentliches Feld, über das gesprungen wird, jeweils
  eines der vorkonfigurierten umkopieren, oder
- das Springen über eine weitere Indirektion machen, also einen
  neuen Zeiger auf das jeweils aktuelle Feld mit den Konfigurationen
  richten und darüber und einen Zeiger darin springen.
  Beispiel:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>

#define MAXKEYS    2

typedef void (*keyfunction_t)(void);

void set1(void);
void set2(void);

void set1(void)
{
  printf( "ich bin set1\n" );
}

void set2(void)
{
  printf( "ich bin set2\n" );
}



// mehrere Zeigertabellen:
keyfunction_t key_call_Konfiguration_Vollmond[MAXKEYS]={ &set1, &set2 };
keyfunction_t key_call_Konfiguration_Neumond [MAXKEYS]={ &set2, &set1 };

// die jeweils aktuelle Tabelle:
keyfunction_t *p_key_call_Konfiguration_aktuell = key_call_Konfiguration_Vollmond;


// ruft zur Demo alle Funktionen der aktuellen Tabelle auf
void tuwas()
{
  // Aufruf der Funktionen der aktuellen Tabelle über
  // p_key_call_Konfiguration_aktuell, um in das richtige Feld zu
  // kommen und darin über Index [0] oder [1]
  p_key_call_Konfiguration_aktuell[0]();
  p_key_call_Konfiguration_aktuell[1]();
}


int main( int nargs, char **args )
{
  printf( "jetzt ist Neumond:\n" );
  p_key_call_Konfiguration_aktuell = key_call_Konfiguration_Vollmond;
  tuwas();

  printf( "jetzt ist Vollmond:\n" );
  p_key_call_Konfiguration_aktuell = key_call_Konfiguration_Neumond;
  tuwas();

  return 0;
}
  Egal, wieviele Einträge in dem Feld jeweils stehen, muss beim
  Umschalten nur ein Zeiger umgesetzt werden.
  Das ist zum einen schnell und zum zweiten sogar atomar.

Autor: S. Hager (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure schnellen Antworten, Super :)

Ich hab irgendwie vermutet dass es mit {} nicht zur Laufzeit geht, denn 
nirgends wo ich nachgesehen habe konnte ich so etwas sehen.

@ Klaus Wachtler:

Danke für dein schönes Codebeispiel, auf diese Art und Weise werde ich 
es auch machen. Alle Zuweisungen sind zur Laufzeit bekannt und sollten 
je nach Anwendung umgeschaltet werden.

Wie mir gerade einfällt brauchen nicht immer alle sondern nur 
aufeinander folgende geändert werden. Das geht aber genauso, ich darf 
halt auf den Ziel-Zeiger nicht beim Element 0 zu schreiben beginnen 
sondern etwas später mit einem offset von +X Elemente.

Autor: S. Hager (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KORREKTUR meines letzten Postings:

Was ich zum Schluss geschrieben habe geht nicht, ich kann nicht einen "4 
Elemente langen Zeiger" teilweise über einen "8 Elemente langen Zeiger" 
ab Element 4 reinschreiben. Das geht vielleicht bei strings wo man 
Schritt für Schritt alle Zeichen abarbeitet, aber nicht wenn man die 
Adresse eines Zeigers auf andere Daten zeigen lässt - da es ja nur eine 
Adresse gibt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was soll nicht gehen? In C soll etwas mit Zeigern nicht gehen?

Es gibt natürlich keine "8 Elemente langen Zeiger" oder "4
Elemente langen Zeiger", aber dafür Zeiger auf 4 oder 8 Elemente.

Und einen Zeiger kann man auf jedes der Elemente eines Feldes zeigen
lassen, warum nicht auch auf die oberen 4 von 8 Elementen?

Das Beispiel so umgebaut, daß es ein Feld mit 8 Zeigern auf Funktionen
hat und tuwas() einmal die unteren 4 benutzt und dann die oberen 4:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>

#define MAXKEYS    8

typedef void (*keyfunction_t)(void);

void set1(void);
void set2(void);
void set3(void);
void set4(void);
void set5(void);
void set6(void);
void set7(void);
void set8(void);

void set1(void)
{
  printf( "ich bin set1\n" );
}

void set2(void)
{
  printf( "ich bin set2\n" );
}

void set3(void)
{
  printf( "ich bin set3\n" );
}

void set4(void)
{
  printf( "ich bin set4\n" );
}

void set5(void)
{
  printf( "ich bin set5\n" );
}

void set6(void)
{
  printf( "ich bin set6\n" );
}

void set7(void)
{
  printf( "ich bin set7\n" );
}

void set8(void)
{
  printf( "ich bin set8\n" );
}



// mehrere Zeigertabellen:
keyfunction_t key_call[MAXKEYS] =
  { &set1,
    &set2,
    &set3,
    &set4,
    &set5,
    &set6,
    &set7,
    &set8,
  };

// die jeweils aktuelle Tabelle:
keyfunction_t *p_key_call_Konfiguration_aktuell = &key_call[0];


// ruft zur Demo alle Funktionen der aktuellen Tabelle auf
void tuwas()
{
  // Aufruf der 4 Funktionen der aktuellen Tabelle über
  // p_key_call_Konfiguration_aktuell, um in das richtige Feld zu
  // kommen und darin über Index [0] bis [3]
  p_key_call_Konfiguration_aktuell[0]();
  p_key_call_Konfiguration_aktuell[1]();
  p_key_call_Konfiguration_aktuell[2]();
  p_key_call_Konfiguration_aktuell[3]();
}


int main( int nargs, char **args )
{
  // die unteren 4 Elemente benutzen:
  printf( "jetzt ist Neumond:\n" );
  p_key_call_Konfiguration_aktuell = &key_call[0];
  tuwas();

  // jetzt die oberen 4:
  printf( "jetzt ist Vollmond:\n" );
  p_key_call_Konfiguration_aktuell = &key_call[4];
  tuwas();

  return 0;
}

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.