mikrocontroller.net

Forum: Compiler & IDEs Funktionszeiger in Struktur


Autor: Edi _2k (edi_2k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe folgende Struktur definiert:

typedef struct
{
    ubyte    State;
    ubyte    PrevState;
    ubyte    Error;
    void     (*ChangeState)(ubyte);
} Status;

Darin enthalten ist ein Zeiger (ChangeState), der auf folgende Funktion 
zeigt: void changeState(ubyte newState)

In meiner Main-Routine deklariere und initialisiere ich eine Variable 
von diesem Typ:

void main(void)
{
         Status a;
         ubyte newState = 1;

  a.PrevState = NULL;
  a.State = stateInit;
  a.Error = noError;
  a.ChangeState = changeState;  // zuweisung des zeigers auf fkt.

         // aufruf der funktion
         a.ChangeState(newState);
         ...
}

meine Frage lautet nun:
Wie muss void changeState(ubyte newState) aufgebaut sein, damit ich 
darin den Wert von a.State ändern kann? Gibt es in C eine Art "this" mit 
der man auf die members der Struktur zugreifen kann?

Gruß
Stefan

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, sowas gibt es in C nicht.  Du müsstest den this-Zeiger explizit
übergeben:
typedef struct status
{
    ubyte    State;
    ubyte    PrevState;
    ubyte    Error;
    void     (*ChangeState)(struct status *, ubyte);
} Status;

...

void main(void)
{
         Status a;
         ubyte newState = 1;

  a.PrevState = NULL;
  a.State = stateInit;
  a.Error = noError;
  a.ChangeState = changeState;  // zuweisung des zeigers auf fkt.

         // aufruf der funktion
         a.ChangeState(&a, newState);
         ...
}

Übrigens ist das keine Initialisierung, sondern eine Zuweisung.  Als
Initialisierung würde es wie folgt aussehen:
void main(void)
{
         Status a = {
             .PrevState = NULL,
             .State = stateInit,
             .Error = noError,
             .ChangeState = changeState
         };
         ubyte newState = 1;

         // aufruf der funktion
         a.ChangeState(&a, newState);
         ...
}

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg Wunsch: Ohne jetzt Klugschei.... spielen zu wollen habe ich eine 
Frage zu deinem Posting. Ich bin nämlich noch nicht so ganz fitt in C 
und möchte das hier lieber geklärt haben, bevor es mich doch noch mehr 
verwirrt oder ich etwas falsches "lerne". Du hast folgendes geschrieben:
typedef struct status
{
    ubyte    State;
    ubyte    PrevState;
    ubyte    Error;
    void     (*ChangeState)(struct status *, ubyte);
} Status;

...

void main(void)
{
         Status a;
         ...
}

Mir geht es hier speziell um den typedef und die Deklaration der 
Variablen a. Dein typedef ist doch so nicht korrekt oder? Du hast nach 
meinem bisherigen Verständnis ja nicht nur einen neuen Datentyp "status" 
angelegt, sondern auch gleich im typedef eine Variable "Status" mit dem 
Datentyp "status" oder? Somit müsstes es in der main() nur "status a;" 
heißen, stimmts?
Dieser Code soll nochmal zeigen, wie ich gedacht hätte, dass es richtig 
ist:
typedef struct
{
    ubyte    State;
    ubyte    PrevState;
    ubyte    Error;
    void     (*ChangeState)(struct status *, ubyte);
} status;

...

void main(void)
{
         status a;
         ...
}
Oder liege ich mal wieder völlig falsch?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du hast nach meinem bisherigen Verständnis ja nicht nur einen neuen
> Datentyp "status" angelegt, sondern auch gleich im typedef eine
> Variable "Status" mit dem Datentyp "status" oder?

Nein, er hat den neuen Typ Status aus der Struktur status gebildet.
Man könnte hier auch schreiben:
typedef struct
{
...
} Status;
Dann besteht der neue Typ aus einer anonymen Struktur.

int i;
-> Variable i

typedef int i;
-> neuer Typ i

struct
{} Status;
-> Variable Status

typedef struct
{} Status;
-> neuer Typ Status

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, dann ist bei dem typedef also der Begriff nach dem Wort "struct" 
nur der Name der Struktur und nicht schon die Bezeichnung des neu 
erstellten Datentyps. Das erklärt natürlich einiges :).

Danke und Gruß,
Marian

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
>> Du hast nach meinem bisherigen Verständnis ja nicht nur einen neuen
>> Datentyp "status" angelegt, sondern auch gleich im typedef eine
>> Variable "Status" mit dem Datentyp "status" oder?
>
> Nein, er hat den neuen Typ Status aus der Struktur status gebildet.
> Man könnte hier auch schreiben:
>
> typedef struct
> {
> ...
> } Status;
> 

Nein, das ginge nicht, weil man innerhalb der Struktur ja einen struct 
status * für den Prototypen der Member-Funktion braucht. Daher darf die 
Struktur nicht anonym sein und muss benamt werden.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja stimmt, in diesem konkreten Fall geht es natürlich nicht.
Ich meinte das eher als allgemeinen Hinweis, um dem "Nebenfrager" die 
Verwirrung bezüglich status und Status zu nehmen. Ich hätte es etwas 
ausführlicher schreiben sollen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:
> Nein, das ginge nicht, weil man innerhalb der Struktur ja einen struct
> status * für den Prototypen der Member-Funktion braucht. Daher darf die
> Struktur nicht anonym sein und muss benamt werden.

Ich hab da auch mal mit zu kämpfen gehabt:
Beitrag "Problem mit cross-reference"

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.