6

采取以下程序:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char a[8] = "Hello, ";
    char b[7] = "world!";

    strcat(a, b);

    cout << a;

    return 0;
}

请注意ab具有与其分配的字符串相同的大小。

文档指出,strcat(a, b)为了工作,a需要足够大以包含连接的结果字符串。

尽管如此,cout << a显示"Hello, world!". 我是否进入了未定义的行为?

4

5 回答 5

12

“我是否进入了未定义的行为?”

是的。a[] 末尾的区域已被覆盖。这次它起作用了,但可能属于其他东西。

这里我使用一个struct来控制内存布局,并演示一下:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    struct S {
        char a[8];
        char b[5];
        char c[7];
    };

    S s;
    strcpy( s.a , "Hello, " );
    strcpy( s.b , "Foo!" );
    strcpy( s.c , "world!" );


    strcat(s.a, s.c);

    cout << s.a << endl;
    cout << s.b << endl;

    cin.get();

    return 0;
}

这输出:

Hello, world!
orld!

代替:

Hello, world!
Foo!

strcat() 已经在 b[] 上踩过。

请注意,在现实生活中的示例中,此类错误可能要微妙得多,并导致您想知道为什么完全无辜的函数调用 250 行之后会崩溃并可怕地烧毁。;-)

编辑:我还可以建议您使用 strcat_s 吗?或者,更好的是 std::strings:

#include <string>
#include <iostream>

using namespace std;

int main()
{
    string a = "Hello, ";
    string b = "world!";
    a = a + b;
    cout << a;
}
于 2013-10-07T17:05:14.720 回答
3

我是否进入了未定义的行为?

是的。


如果文档说a需要足够大以包含连接的结果字符串”,您为什么不简单地相信它呢?有什么好怀疑的?

于 2013-10-07T16:59:32.103 回答
2

strcat does what is says on the tin viz. copies b onto the end of a without any care as to what data is already there. Since both variables are on the stack one after the other things work. But try

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char a[8] = "Hello, ";
    int i =  10;
    char b[7] = "world!";

    strcat(a, b);

    cout << a << i;

return 0;
}

And you will probably get an unexpected result since your stack has been corrupted by strcat

于 2013-10-07T17:06:05.703 回答
2

在您的程序中,数组a不足以包含结果。因此,您的代码是错误的,应该修复。用标准的话来说,您确实在输入未定义的行为,这意味着它可能有效,也可能无效......

于 2013-10-07T17:01:02.100 回答
1

那是正确的....行为未定义。仅仅因为你得到了这个答案并不意味着它下次不会崩溃,因为数组a太小了。

于 2013-10-07T17:00:21.380 回答