LINUX.ORG.RU

История изменений

Исправление LINUX-ORG-RU, (текущая версия) :

Либо делаешь два генерик принта, один для базовых типов, второй для составных имеющих одинаковое количество полей. Либо пишешь как тут ниже «проксирующие» функции. В printf не сувай =) просто структуру по значению, надо совать поля структуры, раскрывать структуру и форматировать вывод значений полей составного типа.

Так что либо вот так, всё в одном

#include <stdio.h>
#include <stdlib.h>

struct DPOINT2
{
   double X,Y;
} DPOINT2;

struct FPOINT2
{
   float X,Y;
} FPOINT2;

#define MSG1 "Значение"
#define MSG2 "вне заданного диапазона\n"

void p_int(int x)
{
    printf( MSG1 " i %d " MSG2, x);
}

void p_long(long x)
{
    printf( MSG1 " l %ld " MSG2, x);
}

void p_double(double x)
{
    printf( MSG1 " d %f  " MSG2, x);
}

void p_float(float x)
{
    printf( MSG1 " f %f  " MSG2, x);
}

void p_fpoint(struct FPOINT2 x)
{
    printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y);
}

void p_dpoint(struct DPOINT2 x)
{
    printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y);
}

#define PRINT(x)                   \
  _Generic( (x),                    \
    int               : p_int,      \
    long              : p_long,     \
    double            : p_double,   \
    float             : p_float,    \
    struct DPOINT2    : p_dpoint,   \
    struct FPOINT2    : p_fpoint )(x)



int main(int argc, char *argv[])
{

    struct DPOINT2 dp = {.X=42.0, .Y=0.42};
    struct FPOINT2 fp = {.X=42.0, .Y=0.42};

    PRINT(dp);
    PRINT(((struct DPOINT2){42.0,0.42}));

    PRINT(fp);
    PRINT(((struct FPOINT2){42.0,0.42}));

    PRINT(1);
    PRINT(1L);
    PRINT(1.0f);
    PRINT(1.0);

    return 0;
}

Либо вот так, раздельно

#include <stdio.h>
#include <stdlib.h>

struct DPOINT2
{
   double X,Y;
} DPOINT2;

struct FPOINT2
{
   float X,Y;
} FPOINT2;


#define MSG1 "Значение"
#define MSG2 "вне заданного диапазона\n"

#define PRINT2(x)                                                       \
  _Generic( (x),                                                        \
    struct DPOINT2    : printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y),\
    struct FPOINT2    : printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y) )

#define PRINT1(x)                                       \
  _Generic( (x),                                        \
    int               : printf( MSG1 " i %d  " MSG2, x),\
    long              : printf( MSG1 " l %ld " MSG2, x),\
    double            : printf( MSG1 " d %f  " MSG2, x),\
    float             : printf( MSG1 " f %f  " MSG2, x) )


int main(int argc, char *argv[])
{

    struct DPOINT2 dp = {.X=42.0, .Y=0.42};
    struct FPOINT2 fp = {.X=42.0, .Y=0.42};

    PRINT2(dp);
    PRINT2(((struct DPOINT2){42.0,0.42}));


    PRINT2(fp);
    PRINT2(((struct FPOINT2){42.0,0.42}));

    PRINT1(1);
    PRINT1(1L);
    PRINT1(1.0f);
    PRINT1(1.0);

    return 0;
}

Ты хочешь просто вот так

#define PRINT1(x)                                       \
  _Generic( (x),                                        \
    int               : printf( MSG1 " i %d  " MSG2, x),\
    long              : printf( MSG1 " l %ld " MSG2, x),\
    double            : printf( MSG1 " d %f  " MSG2, x),\
    float             : printf( MSG1 " f %f  " MSG2, x),\
    struct DPOINT2    : printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y),\
    struct FPOINT2    : printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y) )

Вроде логично смотрится и красиво, только вот работать не будет для базовых типов int и так далее, все попрытки это обойти приведут к починил тут, сломал там и так и будут качели, все поля в одни скобочки, псевдополя для базовых типов, вместо полей передача по значению самой структуры и так далее, но не надо. Это как приводить 42.0 из float к массиву char[4] а потом к uint32_t и ожидать увидеть 42 в значении инта =))) Си это пускает спокойно так как предполагается что ты делаешь с данными то что тебе нужно, и если тебе нужно получить херню непонятную, будет исполнено и ты её получишь =)

Я сам постоянно косячу в этом плане :(
Если я тут где-то ошибаюсь буду рад если поправите :).

Исходная версия LINUX-ORG-RU, :

Либо делаешь два генерик принта, один для базовых типов, второй для составных имеющих одинаковое количество полей. Либо пишешь как тут ниже «проксирующие» функции. В printf не сувай =) просто структуру по значению, надо совать поля структуры, раскрывать структуру и форматировать вывод значений полей составного типа.

Так что либо вот так, всё в одном

#include <stdio.h>
#include <stdlib.h>

struct DPOINT2
{
   double X,Y;
} DPOINT2;

struct FPOINT2
{
   float X,Y;
} FPOINT2;

#define MSG1 "Значение"
#define MSG2 "вне заданного диапазона\n"

void p_int(int x)
{
    printf( MSG1 " i %d " MSG2, x);
}

void p_long(long x)
{
    printf( MSG1 " l %ld " MSG2, x);
}

void p_double(double x)
{
    printf( MSG1 " d %f  " MSG2, x);
}

void p_float(float x)
{
    printf( MSG1 " f %f  " MSG2, x);
}

void p_fpoint(struct FPOINT2 x)
{
    printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y);
}

void p_dpoint(struct DPOINT2 x)
{
    printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y);
}

#define PRINT(x)                   \
  _Generic( (x),                    \
    int               : p_int,      \
    long              : p_long,     \
    double            : p_double,   \
    float             : p_float,    \
    struct DPOINT2    : p_dpoint,   \
    struct FPOINT2    : p_fpoint )(x)



int main(int argc, char *argv[])
{

    struct DPOINT2 dp = {.X=42.0, .Y=0.42};
    struct FPOINT2 fp = {.X=42.0, .Y=0.42};

    PRINT(dp);
    PRINT(((struct DPOINT2){42.0,0.42}));

    PRINT(fp);
    PRINT(((struct FPOINT2){42.0,0.42}));

    PRINT(1);
    PRINT(1L);
    PRINT(1.0f);
    PRINT(1.0);

    return 0;
}

Либо вот так, раздельно

#include <stdio.h>
#include <stdlib.h>

struct DPOINT2
{
   double X,Y;
} DPOINT2;

struct FPOINT2
{
   float X,Y;
} FPOINT2;


#define MSG1 "Значение"
#define MSG2 "вне заданного диапазона\n"

#define PRINT2(x)                                                       \
  _Generic( (x),                                                        \
    struct DPOINT2    : printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y),\
    struct FPOINT2    : printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y) )

#define PRINT1(x)                                       \
  _Generic( (x),                                        \
    int               : printf( MSG1 " i %d  " MSG2, x),\
    long              : printf( MSG1 " l %ld " MSG2, x),\
    double            : printf( MSG1 " d %f  " MSG2, x),\
    float             : printf( MSG1 " f %f  " MSG2, x) )


int main(int argc, char *argv[])
{

    struct DPOINT2 dp = {.X=42.0, .Y=0.42};
    struct FPOINT2 fp = {.X=42.0, .Y=0.42};

    PRINT2(dp);
    PRINT2(((struct DPOINT2){42.0,0.42}));


    PRINT2(fp);
    PRINT2(((struct FPOINT2){42.0,0.42}));

    PRINT1(1);
    PRINT1(1L);
    PRINT1(1.0f);
    PRINT1(1.0);

    return 0;
}

Ты хочешь просто вот так

#define PRINT1(x)                                       \
  _Generic( (x),                                        \
    int               : printf( MSG1 " i %d  " MSG2, x),\
    long              : printf( MSG1 " l %ld " MSG2, x),\
    double            : printf( MSG1 " d %f  " MSG2, x),\
    float             : printf( MSG1 " f %f  " MSG2, x),\
    struct DPOINT2    : printf( MSG1 " d(%6.3f, %6.3f) " MSG2 ,x.X,x.Y),\
    struct FPOINT2    : printf( MSG1 " f(%6.3f, %6.3f) " MSG2 ,x.X,x.Y) )

Вроде логично смотрится и красиво, только вот работать не будет для базовых типов int и так далее, все попрытки это обойти приведут к починил тут, сломал там и так и будут качели, все поля в одни скобочки, псевдополя для базовых типов, вместо полей передача по значению самой структуры и так далее, но не надо. Это как приводить 42.0 из float к массиву char[4] а потом к uint32_t и ожидать увидеть 42 в значении инта =))) Си это пускает спокойно так как предполагается что ты делаешь с данными то что тебе нужно, и если тебе нужно получить херню непонятную, будет исполнено и ты её получишь =)

Я сам постоянно косячу в этом плане :(