typedef int (fc_name) (void);
Hier fc_name
ein beliebiges gültiges C-Symbol ist.
Wie anders ist dies von einem Funktionszeiger typedef
?
Hemanth
typedef int (fc_name) (void);
Hier fc_name
ein beliebiges gültiges C-Symbol ist.
Wie anders ist dies von einem Funktionszeiger typedef
?
jamesdlin
Es ist ein typedef
zu einem Funktionstyp. Die Absicht ist, es für Funktionszeiger zu verwenden, aber in diesem Fall wäre die Syntax, es zu verwenden:
int bar(void);
fc_name* foo = bar; /* Note the * */
Update: Wie in den Kommentaren zu Jonathan Lefflers Antwort erwähnt, die typedef
kann verwendet werden, um Funktionen zu deklarieren. Eine Verwendung könnte darin bestehen, eine Reihe von Callback-Funktionen zu deklarieren:
typedef int (callback)(int, void*);
callback onFoo;
callback onBar;
callback onBaz;
callback onQux;
+1: Ah – so wird es also nützlich! Ich habe dir gezeigt, dass du Recht hast – aber erst, als du mir gezeigt hast, wie. Wir leben, wir lernen; SO rockt.
– Jonathan Leffler
9. September 2010 um 6:34 Uhr
Ich nehme an, Sie müssten immer noch den gesamten Funktionsprototyp für jede Funktionsdefinition einschließen? BEARBEITEN: Egal, die Antwort von Jonathan Leffler hat das angesprochen.
– Hubro
8. Juli 2014 um 2:56 Uhr
Jonathan Leffler
Die erste Klammer ist überflüssig – es ist äquivalent zu:
typedef int fc_name(void);
Ich glaube nicht, dass dies etwas Nützliches bringt, obwohl ich GCC nicht dazu bringen kann, sich darüber zu beschweren.
Das bedeutet, dass fc_name
ist ein Alias für einen Funktionstyp, der keine Argumente akzeptiert und ein zurückgibt int
. Es ist nicht direkt allzu nützlich, obwohl Sie zum Beispiel deklarieren können, dass rand()
Funktion mit:
fc_name rand;
Sie können die nicht verwenden typedef
in einer Funktionsdefinition.
Ein Zeiger auf die Funktion typedef würde lauten:
typedef int (*fc_name)(void);
Dieser Code zeigt, dass die Typedefs ohne das Sternchen keine Funktionszeiger sind (Adressierung einer jetzt gelöschten alternativen Antwort):
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x = function;
fc_name2 y = function;
fc_name3 z = function;
Nach dem Kompilieren sagt ‘gcc’:
gcc -Wextra -Wall -pedantic -c -O x.c
x.c:10:1: error: function ‘x’ is initialized like a variable
x.c:11:1: error: function ‘y’ is initialized like a variable
Und dieser Code zeigt, dass Sie ihn tatsächlich verwenden können fc_name *var = funcname;
wie vorgeschlagen von jamesdlin:
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x_0 = function;
fc_name1 *x_1 = function;
fc_name2 y_0 = function; // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function; // Damn Bessel functions - and no <math.h>
fc_name3 z = function;
Mit y0 generiert y1 GCC-Warnungen:
x.c:12:11: warning: conflicting types for built-in function ‘y0’
x.c:13:11: warning: built-in function ‘y1’ declared as non-function
Und aufbauend auf dem Kommentar von Schot:
static int function(void)
{
return 0;
}
typedef int fc_name1 (void);
typedef int (fc_name2)(void);
typedef int (*fc_name3)(void);
fc_name1 x_0 = function; // Error
fc_name1 *x_1 = function; // x_1 is a pointer to function
fc_name1 x_2; // Declare int x_2(void);
fc_name1 *x_3 = x_2; // Declare x_3 initialized with x_2
fc_name2 y_0 = function; // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function; // Damn Bessel functions - and no <math.h>
fc_name1 y_2; // Declare int y_2(void);
fc_name1 *y_3 = x_2; // Declare y_3 initialized with y_2
fc_name3 z = function;
Interessant – die dunklen Ecken von C sind tatsächlich trüb.
Einige Leute ziehen es vor, dass typedef von der Funktionssignatur Pre-Pointer-Take ist. Das verschiebt die “Explizite”, einen Zeiger auf die Deklaration jedes Funktionszeigers zu nehmen. Es ist eine Frage des Stils, denke ich.
– dezent
9. September 2010 um 6:33 Uhr
Sie können auch eine Funktion verwenden typedef
für eine Funktion Erklärung (Prototyp), aber nicht für a Definition. Aber das ist nicht sehr nützlich, außer zur Verschleierung.
– schott
9. September 2010 um 6:35 Uhr
@schot: Ordentlich, ich wusste nicht, dass es für Funktionsdeklarationen verwendet werden kann. Ich denke tatsächlich, dass das nützlich ist, um eine Reihe von Callback-Funktionen zu deklarieren. zuvor habe ich ein Präprozessor-Makro verwendet, um dies zu vereinfachen.
– jamesdlin
9. September 2010 um 9:22 Uhr
Daniel
Interessant! Eine Typedef-Deklaration ist eine Deklaration mit Typedef als Speicherklasse.
typedef int fc_name1 (void);
// this defines a function type called fc_name1
// which takes no parameter and returns int
später könnten Sie eine Funktion wie folgt definieren,
fc_name1 myFunc;
// this is equivalent to the next line
// int myFunc(void);
Sie sollten dies anhand des c/c++-Standards herausfinden können!
Ich habe noch nie gesehen, dass dies mit einem gemacht wurde typedef-Nameaber Klammern um den Namen von a Funktion sind nützlich, um zu verhindern, dass es als funktionsähnliches Makro mit demselben Namen erweitert wird. Zum Beispiel die isxxx
Funktionen ein ctype.h
sind sowohl als Funktionen als auch als Makros definiert. Dies ist so, dass Sie einen Zeiger darauf nehmen können isalpha
. Aber wie funktioniert die C-Bibliothek definieren das Aus der Reihe isalpha
? Wahrscheinlich so:
#include <ctype.h>
int
(isalpha)(int c)
{
return isalpha(c);
}
Die Verwendung von isalpha
im Funktionskörper wird als Makro erweitert, die Verwendung im Funktionskopf nicht.
Hemanth
1 #include <stdio.h>
2
3
4 typedef int (fc_name)(void);
5
6
7
8 int test_func1 ()
9 {
10 printf("\n test_func1 called\n");
11
12 return 0;
13 }
14
15 int test_func2 (void)
16 {
17 printf("\n test_func2 called\n");
18 return 0;
19 }
20
21 int handler_func(fc_name *fptr)
22 {
23 //Call the actual function
24 fptr();
25 }
26
27 int main(void)
28 {
29 fc_name *f1, *f2;
30
31 f1 = test_func1;
32 f2 = test_func2;
33
34 handler_func(f1);
35 handler_func(f2);
36
37 printf("\n test complete\n");
38
39 return 0;
40 }
AUSGANG:-
test_func1 called
test_func2 called
test complete
Die Typedef, nach der ich gefragt habe (Zeile Nr. 4 hier), stellt einen Funktionstyp dar und ist nicht dasselbe wie die Typedef des Funktionszeigers. Diese Art von Typedef hat nicht viel Bedeutung. Diese werden als Stilstandard verwendet oder einfach, um absichtlich Verschleierung zu erzeugen 😉
Beachten Sie, dass Sie Folgendes verwenden könnten: int handler_func2(fc_name fptr) { return fptr(); }
weil der ‘function’-Parameter automatisch als Funktionszeiger behandelt (in) umgewandelt wird.
– Jonathan Leffler
3. April 2019 um 17:29 Uhr
diablon
Die korrekte Form lautet:
typedef int (*myfunc)(void);
Sie können eine Funktion wie folgt definieren:
int helloword(void) {
printf("hello, world\n");
}
und definieren Sie dann einen Variablenpunkt auf diese Funktion:
myfunc hw_func;
hw_func = helloworld;
und rufen Sie die Funktion mit dem Funktionszeiger auf:
int ret = (*hw_func)();
Der Grund, warum wir einen Funktionszeiger brauchen, ist, dass die C-Sprache keinen vordefinierten Funktionszeiger und keine vordefinierte Verwendung hat void *
Zeiger zum Aufrufen einer Funktion ist in C-Sprache illegal.
Beachten Sie, dass Sie Folgendes verwenden könnten: int handler_func2(fc_name fptr) { return fptr(); }
weil der ‘function’-Parameter automatisch als Funktionszeiger behandelt (in) umgewandelt wird.
– Jonathan Leffler
3. April 2019 um 17:29 Uhr