Forum: Mikrocontroller und Digitale Elektronik [C] Funktion, die Ihren eigenen Typ als Argument bekommt


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 Peter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte eine Funktion deklarieren (oder am besten als typedef), die 
als Argumente eine Integer und einen Funktionszeiger auf genau so eine 
Funktion, wie sie selbst eine ist, akzeptiert.
Wenn ich schreibe
1
typedef int Func_t( int, Func_t* );
geht das ja nicht, weil der Typ Func_t noch nicht bekannt ist.

Aber so geht's auch nicht:
1
typedef int Func_t( int, int(*)() );
2
3
testfunc(int i, Func_t *f) {
4
     return 0;
5
}
6
Func_t *funcptr = testfunc;
Hier meckert der Compiler natürlich, dass *funcptr und testfunc nicht 
vom selben Pointer Typ sind.
Ich müsste casten:
1
Func_t *funcptr = (Func_t*)testfunc;
Kann man denn einen Typ basteln, der als (zweites) Argument einen Zeiger 
auf den eigenen Typ nimmt?

von Tom (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die Lösung für alle abstrusen Probleme in C ist "Das Problem in ein 
struct stecken, schon funktioniert es".
1
#include <stdio.h>
2
3
typedef struct Foo
4
{
5
    void (*call)(struct Foo, int);
6
} Foo;
7
8
void bar(Foo foo, int i)
9
{
10
    if (i <= 0)
11
        return;
12
    printf("%d\n", i);
13
    foo.call(foo, i-1);
14
}
15
16
int main(void)
17
{
18
    bar((Foo){bar}, 7);
19
    return 0;
20
}

von nocheinGast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also in C kann man sowas doch mit dem Präprozessor zusammenbauen 
(vorausgesetzt ich hab überhaupt die Frage richtig verstanden):
1
#define tdef(Name, R, ...) \
2
    typedef R(*Name)(__VA_ARGS__, R(*)(__VA_ARGS__))
3
    
4
tdef(Funktion, int, char, int);
5
6
7
int f(char a, int b, int (*c)(char a, int b)) {
8
    return c(a, b);
9
}
10
11
int x(char a, int b) {
12
}
13
14
void y(char a, int b) {
15
}
16
17
int main() {
18
    Funktion fp = f;
19
    
20
    fp(1, 2, x);
21
    fp(1, 2, y);  // Fehler.
22
}
Ich hoffe, ich mach hier keinen Unsinn...

In C++ könnte man das mit einem Template lösen:
1
#include <functional>
2
3
template <typename R, typename... Args>
4
using Funktion = std::function<R (Args..., std::function<R (Args...)>)>; 
5
6
int f(char a, int b, std::function<int (char a, int b)> c) {
7
    return c(a, b);
8
}
9
10
int x(char a, int b) {
11
}
12
13
void y(char a, int b) {
14
}
15
16
int main() {
17
    Funktion<int, char, int> fp = f;
18
    
19
    fp(1, 2, x);
20
    fp(1, 2, y);  // Fehler.
21
}

von Peter F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> "Das Problem in ein
> struct stecken, schon funktioniert es".
Danke!
Das funktioniert, denn da erscheint das zweite "struct Foo" in einem 
anderen Block, wo es schon bekannt ist.

nocheinGast schrieb:
> Also in C kann man sowas doch mit dem Präprozessor zusammenbauen
Hm, ich glaube nicht, denn auch der Präprozessor muss ja Code 
generieren, den der Compiler als gültig ansieht.

nocheinGast schrieb:
> int f(char a, int b, int (*c)(char a, int b)) {
>     return c(a, b);
> }
Auch hier ist ja *c nicht vom selben Typ wie f.

Beitrag #5699472 wurde vom Autor gelöscht.

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.