【问题标题】:C++ Very weird behavior while using int in switchC++ 在 switch 中使用 int 时非常奇怪的行为
【发布时间】:2012-06-25 14:40:04
【问题描述】:

我在使用以下 switch 语句时遇到了一些非常奇怪的行为:

string recognise_mti(int mti_code)
{
switch(mti_code)
    {
    case 1100:
    case 1101:
        return (mti_code + " (Auth. Request/Repeat)"); break;

    default:
        return (mti_code + " (NOT RECOGNISED)"); break;
    }
}

它似乎根据输入的整数返回各种东西。这可能会变成一个愚蠢的错误,但到目前为止,我无法识别它。感谢任何帮助。

【问题讨论】:

  • 您可能需要详细说明收到的结果。
  • 与您的问题无关,但是当 return 作为 case 中唯一的事情时,您不需要 break。原因是return 返回,break 不会被执行。当然,现代编译器可能会注意到这一点,并且不会为 break 生成代码。
  • @JoachimPileborg 啊,我不知道,谢谢!

标签: c++ int switch-statement case


【解决方案1】:

mti_code" (Auth. Request/Repeat)" 都不是 std::string。所以事实上,加法要做的就是指针加法。所以你最终会得到一个有点随机(并且可能是无效的)指针,然后它被隐式转换为std::string

试试这个:

#include <sstream>

...

std::stringstream ss;
ss << mti_code;
switch(mti_code)
    {
    case 1100:
    case 1101:
        ss << " (Auth. Request/Repeat)"; break;

    default:
        ss << " (NOT RECOGNISED)"; break;
    }
return ss.str();

【讨论】:

  • 啊,感谢您的解释和帮助,现在说得通了,我不得不说,这是一个愚蠢(和尴尬)的错误。 :)
【解决方案2】:

您正在添加一个整数和一个字符串文字。这在 C++ 代码中并不典型。

可能发生的情况是,您正在返回一个由无效字符指针构造的字符串,因为字面量(方式)短于 1100 个字符。

【讨论】:

    【解决方案3】:

    您正在尝试将整数添加到 C 样式的字符串中,这与您的预期不符。字符串被转换为指向其第一个字符的指针,然后该指针增加 1100(或其他)字节,离开字符串的末尾,并进入随机内存。如果幸运的话,程序会崩溃;如果运气不好,函数会返回垃圾。

    您可以使用字符串流来构建字符串:

    std::ostringstream result;
    switch(mti_code)
    {
    case 1100:
    case 1101:
        result << mti_code << " (Auth. Request/Repeat)"; break;
    
    default:
        result << mti_code << " (NOT RECOGNISED)"; break;
    }
    return result.str();
    

    或者在 C++11 中,你可以使用std::to_string 来转换整数:

    return std::to_string(mti_code) + " (Auth. Request/Repeat)";
    

    【讨论】:

    • 哪些编译器支持 C++11?
    【解决方案4】:

    您正在尝试将字符串附加到整数。这在 C 或 C++ 中是不可能的。您必须以某种方式将整数转换为字符串,std::ostringstream 是推荐的方式:

    std::string recognise_mti(const int mti_code)
    {
        std::ostringstream ostr;
    
        switch(mti_code)
        {
        case 1100:
        case 1101:
            ostr << mti_code << " (Auth. Request/Repeat)";
            break;
    
        default:
            ostr << mti_code << " (NOT RECOGNISED)";
            break;
        }
    
        return ostr.str();
    }
    

    或者,如果你有一个支持 C++11 和 std::to_string 的编译器,你可以使用它:

    std::string recognise_mti(const int mti_code)
    {
        switch(mti_code)
        {
        case 1100:
        case 1101:
            return std::to_string(mti_code) + " (Auth. Request/Repeat)";
    
        default:
            return std::to_string(mti_code) + " (NOT RECOGNISED)";
        }
    }
    

    【讨论】:

      【解决方案5】:

      您确实看到您正在将一个整数值添加到给定字符串文字的第一个字节的地址?这基本上是未定义的行为,因为您正在“向右”偏移 1100 处(因为我们正在谈论字符,这是位于内存街道 1100 字节处的某物的地址)。例如,在我的示例中,如果我尝试将给定字符串文字的地址偏移 1100,我会得到“正在初始化”。这是因为偏移地址被返回并隐式转换为一个字符串,该字符串被读取为位于给定地址的任何内容。

      可以是任何东西,我的示例字符串、“crazy大象”或在 MSVC 中启用完整 C++11 支持的秘密方法。 :P

      如果我尝试再将其偏移一个字符(一个字节,向右偏移一个):

      recognise_mti(1100);  // "being initialized."  
      recognise_mti(1101); // "eing initialized."
      

      【讨论】:

        【解决方案6】:

        您不能将整数和字符串文字与+ 连接。您需要先将整数转换为字符串。您可以使用stringstreamsprintf() 执行此操作。

        【讨论】:

          【解决方案7】:

          您将int 添加到const char* 并将其作为string 返回。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-03-13
            • 2011-03-01
            • 2017-07-28
            • 2015-08-05
            • 1970-01-01
            • 2020-12-02
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多