Forum: Compiler & IDEs Funktionszeiger in Struktur


von Edi _. (edi_2k)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nein, sowas gibt es in C nicht.  Du müsstest den this-Zeiger explizit
übergeben:
1
typedef struct status
2
{
3
    ubyte    State;
4
    ubyte    PrevState;
5
    ubyte    Error;
6
    void     (*ChangeState)(struct status *, ubyte);
7
} Status;
8
9
...
10
11
void main(void)
12
{
13
         Status a;
14
         ubyte newState = 1;
15
16
  a.PrevState = NULL;
17
  a.State = stateInit;
18
  a.Error = noError;
19
  a.ChangeState = changeState;  // zuweisung des zeigers auf fkt.
20
21
         // aufruf der funktion
22
         a.ChangeState(&a, newState);
23
         ...
24
}

Übrigens ist das keine Initialisierung, sondern eine Zuweisung.  Als
Initialisierung würde es wie folgt aussehen:
1
void main(void)
2
{
3
         Status a = {
4
             .PrevState = NULL,
5
             .State = stateInit,
6
             .Error = noError,
7
             .ChangeState = changeState
8
         };
9
         ubyte newState = 1;
10
11
         // aufruf der funktion
12
         a.ChangeState(&a, newState);
13
         ...
14
}

von Marian (Gast)


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:
1
typedef struct status
2
{
3
    ubyte    State;
4
    ubyte    PrevState;
5
    ubyte    Error;
6
    void     (*ChangeState)(struct status *, ubyte);
7
} Status;
8
9
...
10
11
void main(void)
12
{
13
         Status a;
14
         ...
15
}

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:
1
typedef struct
2
{
3
    ubyte    State;
4
    ubyte    PrevState;
5
    ubyte    Error;
6
    void     (*ChangeState)(struct status *, ubyte);
7
} status;
8
9
...
10
11
void main(void)
12
{
13
         status a;
14
         ...
15
}
Oder liege ich mal wieder völlig falsch?

von Stefan E. (sternst)


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:
1
typedef struct
2
{
3
...
4
} Status;
Dann besteht der neue Typ aus einer anonymen Struktur.

1
int i;
-> Variable i

1
typedef int i;
-> neuer Typ i

1
struct
2
{} Status;
-> Variable Status

1
typedef struct
2
{} Status;
-> neuer Typ Status

von Gast (Gast)


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

von Johann L. (gjlayde) Benutzerseite


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:
>
1
> typedef struct
2
> {
3
> ...
4
> } Status;
5
>

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.

von Stefan E. (sternst)


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.

von Simon K. (simon) Benutzerseite


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"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.