Sök…


Syntax

  • _Generiskt (tilldelningsuttryck, generisk-associerad-lista)

parametrar

Parameter detaljer
generic-assoc-lista generisk-förening ELLER generisk-associerad-lista, generisk-förening
generic-association typnamn: tilldelningsuttryck ELLER standard: tilldelningsuttryck

Anmärkningar

  1. Alla typkvalificeringar kommer att släppas under utvärderingen av _Generic primärt uttryck.
  2. _Generic primärt uttryck utvärderas i översättningsfas 7 . Så faser som strängtillkoppling har avslutats före utvärderingen.

Kontrollera om en variabel är av en viss kvalificerad typ

#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));
}

Produktion:

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

Men om typen generisk makro implementeras så här:

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

Utgången är:

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

Detta beror på att alla typer av kvalificeringar släpps för utvärderingen av det kontrollerande uttrycket för ett _Generic primärt uttryck.

Typgenerisk utskriftsmakro

#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");
}

Produktion:

int: 42
double: 3.14
unknown argument

Observera att om typen varken är int eller double skulle en varning genereras. För att eliminera varningen kan du lägga till den typen i print(X) .

Generiskt urval baserat på flera argument

Om ett val på flera argument för ett typiskt generiskt uttryck önskas, och alla typer i fråga är aritmetiska typer, är ett enkelt sätt att undvika kapslade _Generic uttryck att använda tillägg av parametrarna i det styrande uttrycket:

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))

Här kontrolleras det kontrollerande uttrycket (X)+(Y) endast enligt dess typ och utvärderas inte. De vanliga omvandlingarna för aritmetiska operander utförs för att bestämma den valda typen.

För mer komplex situation kan ett val göras baserat på mer än ett argument till operatören genom att häcka dem tillsammans.

Detta exempel väljer mellan fyra externt implementerade funktioner som tar kombinationer av två int- och / eller strängargument och returnerar summan.

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 );
}

Även om det verkar som om argument y utvärderas mer än en gång är det inte 1 . Båda argumenten utvärderas endast en gång, i slutet av makro Add: ( x , y ) , precis som i ett vanligt funktionssamtal.


1 (Citat från: ISO: IEC 9899: 201X 6.5.1.1 Generiskt urval 3)
Det kontrollerande uttrycket för ett generiskt urval utvärderas inte.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow