C: Struct function pointer prototype

OP #5923433
Guten Morgen,

ich habe in einem struct einen Funktionszeiger auf eine Funktion, die 
den struct als Parameter übergeben bekommt:
1
typedef struct IconData_s
2
{
3
    void (*fcn) (IconData_t);
4
    uint8_t slot;
5
    int8_t thisState;
6
    int8_t lastState;
7
}
8
IconData_t;
Das funktioniert. Die Funktion läßt sich beim Iterieren über das struct 
array aufrufen.

Will ich stattedessen eine Funktion mit Funktionszeiger als Argument 
aufrufen, schlägt der Build fehl:
1
typedef struct IconData_s
2
{
3
    void (*fcn) (IconData_t *);
4
    uint8_t slot;
5
    int8_t thisState;
6
    int8_t lastState;
7
}
8
IconData_t;
Stattdessen muß ich mit einem "incomplete type struct" hantieren:
1
struct IconData_s;
2
typedef struct IconData_s IconData_t;
3

4
struct IconData_s
5
{
6
    void (*fcn) (IconData_t *);
7
    uint8_t slot;
8
    int8_t thisState;
9
    int8_t lastState;
10
};


Was ist für den Compiler (hier: ARM-GCC) der große Unterschied?
Gast #5923448
Walter T. schrieb:
> Guten Morgen,
>
> ich habe in einem struct einen Funktionszeiger auf eine Funktion, die
> den struct als Parameter übergeben bekommt:typedef struct IconData_s
> {
>     void (*fcn) (IconData_t);
>     uint8_t slot;
>     int8_t thisState;
>     int8_t lastState;
> }
> IconData_t;
> Das funktioniert. Die Funktion läßt sich beim Iterieren über das struct
> array aufrufen.

Bist du sicher, dass das funktioniert? Würde mich wundern.
IcondData_t ist in dieser Zeile noch nicht bekannt.
1
void (*fcn) (IconData_t);
Wenn du die Warnungen einschaltest, sagt dir dein Compiler das auch.
1
warning: parameter names (without types) in function declaration
2
    3 |     void (*fcn) (IconData_t);
3
      |     ^~~~
Der Wortlaut der Warnung ist in diesem Fall nicht ideal, aber sollte 
einen in die richtige Richtung weisen.
OP #5923464
Die Warnung habe ich auch.

Es funktioniert insoweit, als daß das richtige passiert, d.h. die 
Funktion läßt sich korrekt aufrufen und schreibt auch einen Zahlenwert 
aus dem struct korrekt in die Konsole. Aber klar. Die Warnung ist da.

Nur das eine ist ein Fehler - das andere eine Warnung - was ist für den 
Kompiler der große Unterschied?
Gast #5923468
Walter T. schrieb:
> void (*fcn) (IconData_t);

In dieser Zeile ist IconData_t keine Struktur, sondern default int. Du 
wirst einen Compiler mit C89 verwenden.

Das Stichwort ist "vorwärtsdeklaration" und das tut nun wirklich nicht 
so weh, wie es "incomplete type" vermuten lässt.
Gast #5923470
Folgendes sollte funktionieren:
1
typedef struct IconData_s
2
{
3
    void (*fcn) ( struct IconData_s *);
4
    uint8_t slot;
5
    int8_t thisState;
6
    int8_t lastState;
7
}
8
IconData_t;

Gruß Martin
Beitrag #5923472 wurde von einem Moderator gelöscht.
Moderator #5923487
Dieses

1
    void (*fcn) (IconData_t);

ist K&R-C und steht für

1
    void (*fcn) (int IconData_t);

in ISO-C. IconData_t ist also nicht der Argumenttyp, sondern der
Argumentname.

Deswegen erscheint die Warnung

1
warning: parameter names (without types) in function declaration

(Name ist da, aber Typ fehlt)
Moderator #5923515
Clang liefert hier sogar einen Error:

1
test.c:5:18: error: a parameter list without types is only allowed in a
2
      function definition
3
    void (*fcn) (IconData_t);
4
                 ^

Ich habe auf die Schnelle zwar nicht die entsprechende Stelle in der
ISO-Norm gefunden, aber das die Fehlermeldung ist vermutlich
gerechtfertigt, da in K&R-C reine Deklarationen keine Argumentliste
enthalten.

Hier zeigt sich ein weiteres Mal die Problematik von typedef, die darin
besteht, dass syntaktisch nicht zwischen Typ- und Variablennamen
unterschieden werden kann. Im konkreten Fall wird ein Identifier, der
eigentlich als Typname gedacht ist, aber noch nicht deklariert wurde,
als Variablenname interpretiert.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.