Generische Auswahl (C11)
Verwenden Sie das _Generic
-Schlüsselwort, um Code zu schreiben, der zur Kompilierzeit auf Grundlage des Argumenttyps einen Ausdruck auswählt. Dieser Vorgang ähnelt der Überladung in C++, bei der der Typ des Arguments die aufzurufende Funktion auswählt. In diesem Fall wählt der Typ des Arguments aus, welcher Ausdruck ausgewertet werden soll.
Beispielsweise wertet der Ausdruck _Generic(42, int: "integer", char: "character", default: "unknown");
den Typ von 42
aus und sucht in der Liste nach dem entsprechenden Typ (int
). Er findet ihn und gibt "integer"
zurück.
Syntax
generic-selection
:
_Generic
( assignment-expression
, assoc-list
)
assoc-list
:
association
assoc-list
, association
association
:
type-name
: assignment-expression
default
: assignment-expression
Das erste assignment-expression
-Element wird als steuernder Ausdruck bezeichnet. Der Typ des steuernden Ausdrucks wird zur Kompilierzeit bestimmt und mit assoc-list
abgeglichen, um zu ermitteln, welcher Ausdruck ausgewertet und zurückgegeben werden soll. Der steuernde Ausdruck wird nicht ausgewertet. _Generic(intFunc(), int: "integer", default: "error");
führt z. B. nicht zu einem Aufruf von intFunc
zur Laufzeit.
Wenn der Typ des steuernden Ausdrucks bestimmt wird, werden const
, volatile
und restrict
vor dem Abgleich mit assoc-list
entfernt.
Einträge in assoc-list
, die nicht ausgewählt werden, werden nicht ausgewertet.
Einschränkungen
assoc-list
kann denselben Typ nicht mehrmals angeben.assoc-list
kann keine Typen angeben, die miteinander kompatibel sind, z. B. eine Enumeration und den zugrunde liegenden Typ dieser Enumeration.- Wenn eine generische Auswahl nicht über einen Standardwert verfügt, darf der steuernde Ausdruck in der generischen Zuordnungsliste nur einen kompatiblen Typnamen aufweisen.
Beispiel
Eine Möglichkeit, _Generic
zu verwenden, ist ein Makro. Die <tgmath.h>-Headerdatei verwendet _Generic
, um die richtige mathematische Funktion abhängig vom Argumenttyp aufzurufen. Beispielsweise ordnet das Makro für cos
einen Aufruf mit einem float-Wert cosf
zu, während ein Aufruf mit einem komplexen double-Wert ccos
zugeordnet wird.
Im folgenden Beispiel wird gezeigt, wie Sie ein Makro schreiben, das den Typ des Arguments identifiziert, das Sie an das Makro übergeben. "unknown"
wird generiert, wenn kein Eintrag in assoc-list
mit dem steuernden Ausdruck übereinstimmt:
// Compile with /std:c11
#include <stdio.h>
/* Get a type name string for the argument x */
#define TYPE_NAME(X) _Generic((X), \
int: "int", \
char: "char", \
double: "double", \
default: "unknown")
int main()
{
printf("Type name: %s\n", TYPE_NAME(42.42));
// The following would result in a compile error because
// 42.4 is a double, doesn't match anything in the list,
// and there is no default.
// _Generic(42.4, int: "integer", char: "character"));
}
/* Output:
Type name: double
*/
Anforderungen
Kompilieren Sie mit /std:c11
.
Windows SDK 10.0.20348.0 (Version 2104) oder höher. Informationen zum Herunterladen des neuesten SDK finden Sie unter Windows SDK. Anweisungen zum Installieren und Verwenden des SDK für die C11- und C17-Entwicklung finden Sie unter Installieren der Unterstützung für C11 und C17 in Visual Studio.
Siehe auch
/std
(Standardversion für die Sprache festlegen)
Typgenerische Mathematik