我有一个宏,它使用GCC的typeof来创建一个相同类型的宏参数的变量。问题是:如果该参数具有const
类型,则在宏内创建的变量为const
,我无法使用它。例如:
#include <stdio.h>
#define DECR(x) ({typeof(x) y; y = x; y--; y;})
int main(void)
{
const int v = 5;
printf("%d\n", DECR(v));
return 0;
}
编译给出:
$ cc -c -o t.o t.c
t.c: In function 'main':
t.c:9:2: error: assignment of read-only variable 'y'
t.c:9:2: error: decrement of read-only variable 'y'
make: *** [t.o] Error 1
有没有办法复制一个值的类型并取消它的常量?
答案 0 :(得分:9)
如果您不介意可能的算术推广,您可以这样做:
#define DECR(x) ({typeof(x + 0) y; y = x; y--; y;})
诀窍是typeof
的表达式是x + 0
,这是一个r值,所以l值 - 常量(这是你想要避免的)会丢失。 / p>
使用1 * x
可以完成相同的操作,但奇怪的是,+x
和-x
不起作用。
答案 1 :(得分:2)
是否可以在gcc pure C中使用un const typeof?
我不是这样,但这会奏效:
#define DECR(x) __extension__({__typeof__(x) y = x - 1; y;})
请注意,__extension__
用于禁用ISO C forbids braced-groups within expressions[-pedantic]
警告。
答案 2 :(得分:2)
您可以使用C11 _Generic
选项从const
映射到非const
类型:
#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)))
虽然它涉及很多打字,即使你只需要覆盖整体类型。如今,C11还远未被广泛使用。 Live example at Coliru.
答案 3 :(得分:2)
这是一个比较晚的答案,但是如果您不介意使用更多的GCC扩展,您可以这样做(在一定程度上基于先前的答案)。
#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) \
))
它可以如下使用:
#define DECR(x) ({UNCONST(x) y; y = x; y--; y;})
是的,这很丑。
答案 4 :(得分:0)
c中没有 标准 方式来修改const变量或从现有变量中删除说明符。