C++ 在开关中使用 int 时非常奇怪的行为

C++ Very weird behavior while using int in switch

本文关键字:非常 int 开关 C++      更新时间:2023-10-16

使用以下 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;
    }
}

它似乎根据输入整数返回各种内容。这可能会成为一个愚蠢的错误,但到目前为止,我还没有意识到这一点。感谢任何帮助。

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();

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

可能发生的情况是,您返回的字符串是从无效字符指针构造的,因为文本(方式)短于 1100 个字符。

您正在尝试将整数添加到 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 或 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)";
    }
}

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

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

如果我尝试再用一个字符(一个字节,向右偏移一个)来抵消它:

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

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

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