由宏返回的结构变量大小"此运算符不允许在常量表达式中使用#34;

时间:2015-10-01 15:06:27

标签: c struct c-preprocessor

此编译器的任何解决方案ERROR?

#define TYPE_TOTAL 10
#define MAX_SIZE 20

#define NBITS2(n) ((n&2)?1:0)
#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n)))
#define NBITS8(n) ((n&0xF0)?(4+NBITS4(n>>4)):(NBITS4(n)))
#define NBITS16(n) ((n&0xFF00)?(8+NBITS8(n>>8)):(NBITS8(n)))
#define NBITS32(n) ((n&0xFFFF0000)?(16+NBITS16(n>>16)):(NBITS16(n)))
#define NBITS(n) (n==0?0:NBITS32(n)+1)

typedef struct StatsEntry_s
{
    uint32 type:NBITS(TYPE_TOTAL);   
    uint32 subtype:NBITS(MAX_SIZE);         
}  StatsEntry_t;
  

uint32类型:NBITS(TYPE_TOTAL);
  "此运算符不允许使用常量表达式"。

2 个答案:

答案 0 :(得分:1)

编辑:John Bollinger正确地评论说你的宏实际上是有效的常量表达式;事实上,代码使用gcc 4.9.3,VS C ++(http://webcompiler.cloudapp.net/)以及clang 3.5.1进行编译和运行。我们不确定你为什么会遇到问题 - 你使用的编译器是什么?但无论如何,如果你遇到了无法做到这一点的编译器:

我认为你可以用算术代替条件,就像我在评论中建议的最简单的宏一样。例如NBITS4(n): 原文是

#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n)))

这使得两个东西依赖于0xC位,位移计数和添加2.让我们看看。如果匹配,我们要添加2:(n&(0xC)!= 0)* 2如果设置了一个位,则应为2。对于比特移位,我们认为n>> 0是(我认为)n,因此我们可以再次以与之前相同的方式计算依赖于n& 0xC的0或2。这应该产生

#define NBITS4(n) (((n)&(0xC) != 0)*2+NBITS2((n)>>((n)&(0xC) != 0)*2))

我不确定这是否是最简单的方式,我没有测试它,但它应该是一个开始。

技术性:始终包含您的宏参数;定义是文本替换,可以扩展为令人惊讶的表达。

总的来说:计算比现代CPU上的跳转要快得多。有时使用布尔值作为数字而不是分支条件会带来惊人的性能提升。缺点是它绝对不可读,就像这里一样。

答案 1 :(得分:0)

您可以在没有三元运算符的情况下重新定义宏。这只能达到255,但可以轻松扩展:

#define NBITS2(n) (((!(n&2))*(n&1))|(n&2))
#define NBITS4(n) (((!(n&4))*NBITS2(n))|(((n&4)>>2)*3))
#define NBITS8(n) (((!(n&8))*NBITS4(n))|(((n&8)>>3)*4))
#define NBITS16(n) (((!(n&16))*NBITS8(n))|(((n&16)>>4)*5))
#define NBITS32(n) (((!(n&32))*NBITS16(n))|(((n&32)>>5)*6))
#define NBITS64(n) (((!(n&64))*NBITS32(n))|(((n&64)>>6)*7))
#define NBITS(n) (((!(n&128))*NBITS64(n))|(((n&128)>>7)*8))