Was bedeutet eine Typedef mit Klammern wie “typedef int (f)(void)”? Ist es ein Funktionsprototyp?

Lesezeit: 6 Minuten

Benutzer-Avatar
Hemanth

typedef int (fc_name) (void);

Hier fc_name ein beliebiges gültiges C-Symbol ist.

Wie anders ist dies von einem Funktionszeiger typedef?

Benutzer-Avatar
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


Benutzer-Avatar
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

Benutzer-Avatar
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.

Benutzer-Avatar
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

Benutzer-Avatar
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

1385500cookie-checkWas bedeutet eine Typedef mit Klammern wie “typedef int (f)(void)”? Ist es ein Funktionsprototyp?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy