【问题标题】:Switch not working in C++开关在 C++ 中不起作用
【发布时间】:2013-04-26 13:26:28
【问题描述】:

我今天遇到了一个很奇怪的问题。让我们考虑以下代码:

int llex(){
    cout<<"enter 1"<<endl;
    char32_t c = U'(';
    cout<<(c==U'#')<<endl;
    switch(c){
    case U'#':
        cout<<"enter 2"<<endl;
        return 5;
    default:
        break;
    }
}

int main( int argc, char** argv)
{
    cout<<"enter 1"<<endl;
    char32_t c = U'(';
    cout<<(c==U'#')<<endl;
    switch(c){
    case U'#':
        cout<<"enter 2"<<endl;
        return 5;
    default:
        break;
    }

    cout << "------------" << endl;
    llex();
}

输出是:

enter 1
0
------------
enter 1
0
enter 2

请注意 main 中的代码与 llex 函数中的代码相同。为什么他们输出不同的结果? (我在 clang 上使用 C++11)。

【问题讨论】:

  • llex 中缺少一个括号。你确定其他一切都正确吗?
  • 行为未定义,因为llex() 不返回int
  • 我会从 main 中删除 return 5;
  • 因为UB太棒了
  • @Angew 比如,假设这种情况不会发生,并从代码中抑制它。换句话说,编译器知道default 情况不会发生(因为这会导致未定义的行为),并且由于只有另一种情况,所以生成它。

标签: c++ unicode c++11 switch-statement string-literals


【解决方案1】:

您的llex() 函数应该总是返回一个值,但事实并非如此。如果控制流未命中return 语句,则这是未定义的行为。根据 C++11 标准的第 6.6.3/2 段:

从函数的末尾流出相当于没有值的返回; 这会导致未定义 值返回函数中的行为

除非您解决此问题,否则您不能对您的程序做出任何假设,也不能对其抱有期望。

例如,我无法重现 this fixed live example 中的行为。

【讨论】:

  • 在编译时使用g++ -Wall -std=c++11 以获取针对此行为的警告
  • 并解释可能发生的事情;编译器看到一条控制路径从函数的末尾流出而没有返回,并得出结论认为该路径永远不会被采用。在此基础上,它会导致 switch 语句无条件地采用另一条路径。
  • @bames53:+1,非常有趣
【解决方案2】:

您在函数中缺少用于 switch 的函数结束返回语句和右花括号。

int llex(){
    cout<<"enter 1"<<endl;
    char32_t c = U'(';
    cout<<(c==U'#')<<endl;
    switch(c){
    case U'#':
        cout<<"enter 2"<<endl;
        return 5;
    default:
        break;
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多