Buscar..


Sintaxis

  • _Generic (asignación-expresión, generic-assoc-list)

Parámetros

Parámetro Detalles
lista-assoc-genérica asociación genérica O asociación-genérica-asociación, asociación-genérica
asociación genérica nombre-tipo: expresión-asignación O por defecto: expresión-asignación

Observaciones

  1. Todos los calificadores de tipo se eliminarán durante la evaluación de la expresión primaria _Generic .
  2. _Generic expresión primaria _Generic se evalúa en la fase de traducción 7 . Así que las fases como la concatenación de cuerdas se han terminado antes de su evaluación.

Compruebe si una variable es de un determinado tipo calificado

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

Salida:

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

Sin embargo, si la macro genérica de tipo se implementa así:

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

La salida es:

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

Esto se debe a que todos los calificadores de tipo se eliminan para la evaluación de la expresión de control de una expresión primaria _Generic .

Tipo genérico de impresión macro

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

Salida:

int: 42
double: 3.14
unknown argument

Tenga en cuenta que si el tipo no es int ni double , se generará una advertencia. Para eliminar la advertencia, puede agregar ese tipo a la macro de print(X) .

Selección genérica basada en múltiples argumentos.

Si se desea una selección en múltiples argumentos para un tipo de expresión genérica, y todos los tipos en cuestión son tipos aritméticos, una manera fácil de evitar las expresiones _Generic anidadas es usar la adición de los parámetros en la expresión de control:

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

Aquí, la expresión de control (X)+(Y) solo se inspecciona según su tipo y no se evalúa. Las conversiones habituales para los operandos aritméticos se realizan para determinar el tipo seleccionado.

Para una situación más compleja, se puede realizar una selección basada en más de un argumento para el operador, al anidarlos juntos.

Este ejemplo selecciona entre cuatro funciones implementadas externamente, que toman combinaciones de dos int y / o argumentos de cadena, y devuelven su suma.

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

Aunque parece que el argumento y se evalúa más de una vez, no es 1 . Ambos argumentos se evalúan solo una vez, al final de la macro Agregar: ( x , y ) , al igual que en una llamada de función ordinaria.


1 (Citado de: ISO: IEC 9899: 201X 6.5.1.1 Selección genérica 3)
La expresión de control de una selección genérica no se evalúa.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow