【问题标题】:Switch error:: cannot appear in a constant-expression切换错误:: 不能出现在常量表达式中
【发布时间】:2010-09-29 15:20:18
【问题描述】:

这是一个奇怪的...

我正在玩一些减压算法。我没有通过char buffer[] 循环直到找到buffer[i] 中的停止位,而是尝试使用一些位掩码技术,但使用字符。

我有以下例子:

// In a *.h file  
const char ch = '\x81';  
// To avoid Endianess  
union CharUInt  
{  
    char sz[4];  
    unsigned int u;  
};  
// Legal because char[] is declared before uint32 in the union  
const CharUInt Mask1 = {'\x81', '\x0', '\x0', '\x81'};  
const CharUInt Mask2 = {'\x0', '\x81', '\x81', '\x0'};  
// Proxy / Auxillary uint32 as usimg Mask2.u in the switch blocked produced the same errors  
const unsigned int uMask1 = Mask1.u;  
const unsigned int uMask2 = Mask2.u;  
const unsigned int uMask_ = (uMask1 & uMask2);  
// buf is always long enough  
bool Foo(char buf[])  
{  
    const CharUInt Type = {buf[0], buf[1], buf[2], buf[3]};  
    unsigned int uType = (Type.u & uMask_);  
    switch(uType)  
    {  
    case uMask1:  
        // do stuff  
    case uMask2:    
        // do more stuff  
        return true;  
        break;  
    default:  
        // do different stuff  
        return false;  
        break;  
    }  
};  

不考虑 union 东西的语法(实际代码编译运行良好)并且不考虑 Foo 的函数返回是否漂亮,我得到
'uMask1' cannot appear in a constant-expression
如果使用工会本身,我会得到
'Mask1' cannot appear in a constant-expression
'.' cannot appear in a constant-expression
当然,错误也适用于 uMask2 和 Mask2.u

我错过了什么?

提前致谢

【问题讨论】:

  • 联合声明后的冒号是有意的吗?
  • 您的错误指出了原因。 uMask1 应替换为您需要检查的常量数据,而不是 uMask1。

标签: c++ compiler-errors switch-statement


【解决方案1】:

混淆来自于 const 和 const 是两个这一事实。

switch 语句中的 case 需要“常量表达式”。或者换句话说:编译器可以在编译时“计算”的表达式。 这可能是一个硬编码的数字(如 42),或者之前已定义为数字的东西(使用 #define)。

Const 也被编译器使用,意思是“一旦这个变量有一个值,它就不会再改变了”。例如。在以下代码中:

void myFunction (const int value)
{
...
}

值将是常量。我将无法更改 const 的值,但这不会使其成为编译器的“常量表达式”。

在您的情况下, uMask1 是 const (不能再更改它),但不是常量表达式。

【讨论】:

  • 但是为什么编译器不能在编译时计算出uMask1uMask2的值呢?它拥有执行此操作所需的所有信息。
  • 是的,理论上它可以做到这一点,但编译器不必这样做。这就是 C++11 添加 constexpr 关键字的原因。它告诉编译器它应该在编译时而不是运行时评估表达式。尽管我在您的情况下尝试过,但似乎没有帮助:-(
【解决方案2】:

case条件表达式必须为整型,或可转换为整型,且必须为const。

6.4.2 [stmt.switch]

条件应为整数 类型、枚举类型或类 单次转换的类型 函数积分或枚举 类型存在(12.3)。如果条件 是类类型,条件是 通过调用该转换进行转换 函数和结果 转换用于代替 剩余部分的原始状态 本节的。整体促销 执行。内的任何声明 switch 语句可以被标记 带有一个或多个案例标签 如下:

case 常量表达式:

常量表达式的位置 一个整数常量表达式。这 积分常数表达式 (5.19) 是 隐式转换为提升的 开关条件的类型。没有两个 相同的 case 常数 开关后应具有相同的值 转换为提升的类型 切换条件。

你的表达式不是一个常量表达式,即使变量本身是const,所以你不能打开它。您需要使用if

你还有另一个问题:

你创建一个union

union CharUInt  
{  
    char sz[4];  
    unsigned int u;  
};

...然后您初始化该联合的sz 成员,

static const CharUInt Mask1 = {'\x81', '\x0', '\x0', '\x81'};  

...然后您访问该联合的u 成员。

static const unsigned int uMask1 = Mask1.u;  

根据标准,这会引发未定义的行为。在标准的语言中,工会的 2 名成员不能同时处于活动状态。这意味着您不能像对待施法者一样对待工会。

【讨论】:

  • 您好约翰,感谢您的回答。除了为所有可能和有趣的字节序做 ifdef 之外,还有其他技巧吗?另外,你是什么意思'工会的两个成员不能同时活跃'?在代码中它实际上是 typedef struct _tagType{ union {...}; } TypeT;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多