Was bedeutet diese typedef-Anweisung?

76

Auf einer C ++ - Referenzseite finden Sie einige typedef-Beispiele, und ich versuche zu verstehen, was sie bedeuten.

// simple typedef
typedef unsigned long mylong;


// more complicated typedef
typedef int int_t, *intp_t, (&fp)(int, mylong), arr_t[10];

Also das einfache typedef (die erste Deklaration) verstehe ich.

Aber was erklären sie mit dem zweiten (unten wiederholt)?

typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10];

Was bedeutet (&fp)(int, mylong)das besonders?

rsgmon
quelle
47
Es sollte beachtet werden, dass das Schreiben eines solchen einzeiligen Typedef Goo eine sehr schlechte Programmierpraxis ist, da es schwer zu lesen ist und keinerlei Vorteile daraus resultiert. Wenn Sie dies lesen und noch nie solche Typedefs gesehen haben, verwenden Sie diese Syntax bitte nicht.
Lundin
3
@ Lundin Ich bin anderer Meinung. Wenn Sie sie alle in eine Zeile setzen, wird deutlich, dass Sie beabsichtigen, dass sie sich alle auf denselben Basistyp beziehen. Per Definition.
Herr Lister
9
@MrLister Wenn Sie sie jeweils in einer separaten Zeile nacheinander schreiben, beginnt jede Zeile mit typedef some_type ...und Sie haben mehrere Zeilen wie diese, Ihre Absichten sind sehr klar und es gibt keinen Platz für Syntaxfehler. Weitaus lesbarer.
Lundin
2
@Lundin Es kann Geschmackssache sein, daher bin ich mir nicht sicher, ob wir darüber diskutieren müssen.
Herr Lister

Antworten:

96

Es werden mehrere Typedefs gleichzeitig deklariert, genauso wie Sie mehrere Variablen gleichzeitig deklarieren können. Sie sind alle Typen, die auf basieren int, aber einige werden in zusammengesetzte Typen geändert.

Teilen wir es in separate Erklärungen auf:

typedef int int_t;              // simple int
typedef int *intp_t;            // pointer to int
typedef int (&fp)(int, ulong);  // reference to function returning int
typedef int arr_t[10];          // array of 10 ints
Mike Seymour
quelle
5
Während meiner jahrelangen Programmierung von C ++ wusste ich das nicht! Ich glaube, mein Lehrer glaubte nicht, dass es notwendig war, das zu lernen, und ich fand nie etwas darüber. +1
John Odom
17
Ihr Lehrer hatte recht. Dies ist schwerer zu lesen, eine Funktion, die Sie nicht verwenden sollten.
Plutor
41
typedef int int_t, *intp_t, (&fp)(int, mylong), arr_t[10];

ist äquivalent zu:

typedef int int_t;
typedef int *intp_t;
typedef int (&fp)(int, mylong);
typedef int arr_t[10];

Es gibt tatsächlich ein ähnliches Beispiel im C ++ 11-Standard:

C ++ 11 7.1.3 Der typedefBezeichner

Ein typedef-name führt keinen neuen Typ ein, wie es eine classDeklaration (9.1) oder enumDeklaration tut. Beispiel: after

typedef int MILES , * KLICKSP ;

die Konstruktionen

MILES distance ;
extern KLICKSP metricp ;

sind alle korrekten Erklärungen; Die Art der Entfernung ist int der von metricpist "Zeiger auf int". - Beispiel beenden

Yu Hao
quelle
13
Nach meinem Verständnis ist die Antwort richtig. Warum gibt es eine negative Abstimmung?
Dipto
32

Wenn Sie den cdeclBefehl haben, können Sie ihn verwenden, um diese Deklarationen zu entmystifizieren.

cdecl> explain int (&fp)(int, char)
declare fp as reference to function (int, char) returning int
cdecl> explain int (*fp)(int, char)
declare fp as pointer to function (int, char) returning int

Wenn Sie dies nicht haben cdecl, sollten Sie es auf die übliche Weise installieren können (z. B. auf Debian-Systemen mit sudo apt-get install cdecl).

Amarghosh
quelle
@athos Fromsudo apt-get install cdecl
Amarghosh
Oh, also ist es nicht für Windows?
Athos
0

Der (&fp)(int, mylong)Teil repräsentiert einen Verweis auf eine Funktion. Es wird nicht empfohlen, dass Programmierer Funktionen verwenden, genau typedefaus dem Grund, aus dem Sie diese Frage stellen. Es verwirrt andere Leute, die sich den Code ansehen.

Ich vermute, sie verwenden das typedefin so etwas:

typedef unsigned long mylong; //for completeness
typedef int (&fp)(int, mylong);
int example(int param1, mylong param2);

int main() {
     fp fp_function = example;
     int x = fp_function(0, 1);
     return 0;
}

int example(int param1, mylong param2) {
     // does stuff here and returns reference
     int x = param1;
     return x;
}

Bearbeitet in Übereinstimmung mit Brians Kommentar:

int(&name)(...)ist eine aufgerufene Funktionsreferenzname (die Funktion gibt ein int zurück)

int &name(...)ist eine Funktion, die als name Rückgabe einer Referenz auf ein int bezeichnet wird

Ein Verweis auf eine Funktion, die einen intVerweis zurückgibt, würde ungefähr so ​​aussehen: typedef int &(&fp)(int, mylong)(Dies wird in einem Programm kompiliert, aber das Verhalten ist nicht getestet).

ub3rst4r
quelle
3
Nein, int&(int, mylong)ist ein anderer Typ als int(&)(int, mylong). Ersteres ist eine Funktion, auf die ein Verweis zurückgegeben wird int. Letzteres bezieht sich auf eine zurückkehrende Funktion int. Verweise auf Funktionen sind unklar und nicht sehr nützlich, existieren jedoch in C ++.
Brian
Sicher ist es ein bisschen kompliziert, aber was ist die Alternative? Verwenden Sie kein typedef? Sie benötigen den Typ immer noch, aber ohne typedef müssen Sie explizit denselben Funktionstyp überall dort verwenden, wo er benötigt wird. Dies ist zehnmal verwirrender und natürlich fehleranfällig. Anstatt ein typedef richtig machen zu müssen, muss der Programmierer den Typ an vielen Stellen richtig machen.
Gnasher729
2
"es wird empfohlen" von wem? Typedefs für Funktionszeiger werden sehr häufig in zahlreichen C-APIs für Rückrufe verwendet. Die Verwendung eines Typedef bedeutet, dass die Funktion, die einen Funktionszeiger als Parameter verwendet, viel besser lesbar ist. Wenn Sie keine C ++ - Lambdas verwenden können, sind Funktionszeigertypedefs IMO-Codierungsstile viel besser als die direkte Verwendung, wenn Sie z. B. eine asynchrone API implementieren.
uliwitness
-7

typedef definiert einen neuen Typ zur Verwendung in Ihrem Code, z. B. eine Kurzform.

typedef typename _MyBase::value_type value_type;
value_type v;
//use v

Der Typname hier lässt den Compiler wissen, dass value_type ein Typ und kein Objekt in _MyBase ist.

Das :: ist der Bereich des Typs. Es ist so ähnlich wie "ist in", also ist value_type "in" _MyBase ". oder kann auch als enthalten angesehen werden.

Mögliches Duplikat: C ++ - Bedeutung einer Anweisung, die typedef und typename kombiniert

Hart
quelle
10
Diese Antwort ist nicht hilfreich. Die Frage besagt eindeutig, dass sie das Grundkonzept eines typedef(das Sie erklärt haben) verstehen , aber durch das komplexere (das Sie nicht einmal angesprochen haben) verwirrt waren.
Mirabilos