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