Suche…


Syntax

  • _Generic (Zuweisungsausdruck, generische Assoc-Liste)

Parameter

Parameter Einzelheiten
generische assoc-liste generic-association ODER generic-assoc-liste, generic-association
generische Vereinigung Typname: Zuweisungsausdruck ODER Standard: Zuweisungsausdruck

Bemerkungen

  1. Alle _Generic werden während der Auswertung des _Generic Primärausdrucks _Generic .
  2. _Generic Primärausdruck wird in Übersetzungsphase 7 ausgewertet. Daher wurden Phasen wie die Verkettung von Strings vor der Auswertung abgeschlossen.

Prüfen Sie, ob eine Variable einen bestimmten qualifizierten Typ hat

#include <stdio.h> 

#define is_const_int(x) _Generic((&x),  \
        const int *: "a const int",     \
        int *:       "a non-const int", \
        default:     "of other type")

int main(void)
{
    const int i = 1;
    int j = 1;
    double k = 1.0;
    printf("i is %s\n", is_const_int(i));
    printf("j is %s\n", is_const_int(j));
    printf("k is %s\n", is_const_int(k));
}

Ausgabe:

i is a const int
j is a non-const int
k is of other type

Wenn jedoch das generische Typmakro folgendermaßen implementiert ist:

#define is_const_int(x) _Generic((x), \
        const int: "a const int",     \
        int:       "a non-const int", \
        default:   "of other type")

Die Ausgabe ist:

i is a non-const int
j is a non-const int
k is of other type

Dies liegt daran, dass alle _Generic für die Auswertung des steuernden Ausdrucks eines _Generic Primärausdrucks _Generic .

Typisches generisches Druckmakro

#include <stdio.h>

void print_int(int x) { printf("int: %d\n", x); }
void print_dbl(double x) { printf("double: %g\n", x); }
void print_default() { puts("unknown argument"); }

#define print(X) _Generic((X), \
        int: print_int, \
        double: print_dbl, \
        default: print_default)(X)

int main(void) {
    print(42);
    print(3.14);
    print("hello, world");
}

Ausgabe:

int: 42
double: 3.14
unknown argument

Wenn der Typ weder int noch double , wird eine Warnung generiert. Um die Warnung zu beseitigen, können Sie diesen Typ zum Makro print(X) hinzufügen.

Generische Auswahl basierend auf mehreren Argumenten

Wenn eine Auswahl mehrerer Argumente für einen generischen _Generic gewünscht wird und alle _Generic Typen arithmetische Typen sind, können verschachtelte _Generic Ausdrücke auf einfache Weise _Generic indem die Parameter im steuernden Ausdruck _Generic :

int max_int(int, int);
unsigned max_unsigned(unsigned, unsigned);
double max_double(double, double);

#define MAX(X, Y) _Generic((X)+(Y),                \
                           int:      max_int,      \
                           unsigned: max_unsigned, \
                           default:  max_double)   \
                    ((X), (Y))

Hier wird der steuernde Ausdruck (X)+(Y) nur nach Typ geprüft und nicht ausgewertet. Die üblichen Konvertierungen für arithmetische Operanden werden durchgeführt, um den ausgewählten Typ zu bestimmen.

In einer komplexeren Situation kann eine Auswahl auf der Grundlage mehrerer Argumente für den Bediener getroffen werden, indem diese verschachtelt werden.

In diesem Beispiel werden vier extern implementierte Funktionen ausgewählt, die Kombinationen von zwei Argumenten int und / oder string annehmen und deren Summe zurückgeben.

int AddIntInt(int a, int b);
int AddIntStr(int a, const char* b);
int AddStrInt(const char*  a, int b );
int AddStrStr(const char*  a, const char*  b);

#define AddStr(y)                            \
   _Generic((y),         int: AddStrInt,     \
                        char*: AddStrStr,    \
                  const char*: AddStrStr )

#define AddInt(y)                            \
   _Generic((y),          int: AddIntInt,    \
                        char*: AddIntStr,    \
                  const char*: AddIntStr )

#define Add(x, y)                            \
   _Generic((x) ,        int: AddInt(y) ,    \
                       char*: AddStr(y) ,    \
                 const char*: AddStr(y))     \
                         ((x), (y))

int main( void )
{
    int result = 0;
    result = Add( 100 , 999 );
    result = Add( 100 , "999" );
    result = Add( "100" , 999 );
    result = Add( "100" , "999" );

    const int a = -123;
    char b[] = "4321";
    result = Add( a , b );

    int c = 1;
    const char d[] = "0";
    result = Add( d , ++c );
}

Obwohl es so aussieht, als würde Argument y mehr als einmal ausgewertet, ist es nicht 1 . Beide Argumente werden nur einmal am Ende des Makros Add: ( x , y ) ausgewertet, genau wie bei einem normalen Funktionsaufruf.


1 (Zitiert aus: ISO: IEC 9899: 201X 6.5.1.1 Generische Auswahl 3)
Der steuernde Ausdruck einer generischen Auswahl wird nicht ausgewertet.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow