Is it possible to un-const typeof in gcc pure C?

后端 未结 5 1168
误落风尘
误落风尘 2021-02-19 14:42

I have a macro that uses GCC\'s typeof to create a variable of the same type of a macro argument. The problem is: if that argument has const type, the variable crea

相关标签:
5条回答
  • 2021-02-19 15:22

    You could use a C11 _Generic selection to map from const to non-const type:

    #define DECR_(t, x) ({ t y = (x); --y; y; })
    #define DECR(x) _Generic((x),                     \
        int: DECR_(int, (x)),                         \
        const int: DECR_(int, (x)),                   \
        long: DECR_(long, (x)),                       \
        const long: DECR_(long, (x)),                 \
        unsigned int: DECR_(unsigned int, (x)),       \
        const unsigned int: DECR_(unsigned int, (x)), \
        long long: DECR_(long long, (x)),             \
        const long long: DECR_(long long, (x)))
    

    Although it involves a LOT of typing, even if you only need to cover integral types. C11 is also far from being widely available these days. Live example at Coliru.

    0 讨论(0)
  • 2021-02-19 15:26

    There is no standard way in c to modify a const variable or remove the specifier from an existing one.

    0 讨论(0)
  • 2021-02-19 15:36

    If you don't mind the possible arithmetic promotion you can do this:

    #define DECR(x) ({typeof(x + 0) y; y = x; y--; y;})
    

    The trick is that the expression for typeof is x + 0, which is a r-value, and so the l-value-constness (which is what you want to avoid) is lost.

    The same trick can be done with 1 * x, but curiously enough, +x and -x don't work.

    0 讨论(0)
  • 2021-02-19 15:42

    Is it possible to un-const typeof in gcc pure C?

    I don't thing so, but this will work:

    #define DECR(x) __extension__({__typeof__(x) y = x - 1; y;})
    

    Note that __extension__ is used for disable ISO C forbids braced-groups within expressions[-pedantic] warning.

    0 讨论(0)
  • 2021-02-19 15:45

    This is a rather late answer, but if you don't mind using more GCC extensions you can do this like this (building upon a previous answer somewhat).

    #define UNCONST_HAX_(TYPE) ({TYPE _tmp_macro_var_; _tmp_macro_var_;})
    #define UNCONST(x)                                                      \
        __typeof__(_Generic((x),                                            \
                signed char:              UNCONST_HAX_(signed char),        \
                const signed char:        UNCONST_HAX_(signed char),        \
                unsigned char:            UNCONST_HAX_(unsigned char),      \
                const unsigned char:      UNCONST_HAX_(unsigned char),      \
                short:                    UNCONST_HAX_(short),              \
                const short:              UNCONST_HAX_(short),              \
                unsigned short:           UNCONST_HAX_(unsigned short),     \
                const unsigned short:     UNCONST_HAX_(unsigned short),     \
                int:                      UNCONST_HAX_(int),                \
                const int:                UNCONST_HAX_(int),                \
                unsigned:                 UNCONST_HAX_(unsigned),           \
                const unsigned:           UNCONST_HAX_(unsigned),           \
                long:                     UNCONST_HAX_(long),               \
                const long:               UNCONST_HAX_(long),               \
                unsigned long:            UNCONST_HAX_(unsigned long),      \
                const unsigned long:      UNCONST_HAX_(unsigned long),      \
                long long:                UNCONST_HAX_(long long),          \
                const long long:          UNCONST_HAX_(long long),          \
                unsigned long long:       UNCONST_HAX_(unsigned long long), \
                const unsigned long long: UNCONST_HAX_(unsigned long long), \
                float:                    UNCONST_HAX_(float),              \
                const float:              UNCONST_HAX_(float),              \
                double:                   UNCONST_HAX_(double),             \
                const double:             UNCONST_HAX_(double),             \
                long double:              UNCONST_HAX_(long double),        \
                const long double:        UNCONST_HAX_(long double)         \
        ))
    

    And it could be used as follows:

    #define DECR(x) ({UNCONST(x) y; y = x; y--; y;})
    

    Yes, it is pretty ugly.

    0 讨论(0)
提交回复
热议问题