C和C ++之间的差异:数组大小不受尊重

时间:2014-05-14 13:12:12

标签: c++ c arrays

我学习C ++并且发现了一个我不理解的行为。如果我用C编写以下程序:

#include <stdio.h>

int main() {
    char question[] = "What is your name? ";
    char answer[2];
    printf(question);
    scanf("%ls", answer);
    printf("%s\n", answer);
    return 0;
}

当我输入一个超过两个字节的名字时,答案就是胡言乱语,但即使我不确切知道原因,我也知道出了问题并试图恢复。
相反,如果我编写这个C ++程序(有点等同于前者):

#include <iostream>

using namespace std;

int main() {
    char question[] = "What is your name? ";
    char answer[2];
    cout << question;
    cin >> answer;
    cout << answer << endl;
    return 0;
}

我期待类似的行为,因为我将answer声明为char数组而不是字符串(可以动态调整其大小)。但是当我输入很长的东西时,它会在我输入时打印出来。一个例子:

$ ./test
What is your name? asdfa
asdfa
$ ./test
What is your name? sdhjklwertiuoxcvbnm
sdhjklwertiuoxcvbnm

那么,这里发生了什么?作为第二个问题,当我输入更长的东西时,C中会发生什么?

编辑:为了澄清,我知道我可以使用std::string而不是char数组(我已经在^^上面写了它)。我有兴趣知道为什么这些程序展示 行为。现在我知道它的未定义行为。另外,我更正了C程序(scanf)中的错误。

4 个答案:

答案 0 :(得分:12)

char answer[2];表示您的数组只能包含2个字符。如果你超过这个,那么内存就会溢出并且是未定义的行为。如果使用数组不是必需的,则在数组中保留足够的空间,或者更好地使用std::string。而另一个答案指出,你正在以错误的方式接受输入。

答案 1 :(得分:9)

这是未定义的行为(UB):

scanf(answer);

scanf函数会将answer的未初始化内容解释为格式字符串,从而导致UB。

应该是这样的:

scanf("%1s", answer);

请注意,当您声明大小为2的字符数组时,这意味着它可以适合长度最多为1的C字符串,因为您需要一个字符用于空终止符。

请注意,当您在C ++程序中为名称输入两个以上的字符时,您也会得到未定义的行为:写入数组的末尾是UB。幸运的是,很少需要在C ++中将字符串读入字符数组,因为标准C ++库提供了动态调整大小的类std::string,这是表示字符串的更好选择。

答案 2 :(得分:6)

你不能指望类似的行为。

在这两种情况下都可以预期未定义的行为:在两种语言中超出内存缓冲区未定义的行为,所以绝对允许任何事情发生。

答案 3 :(得分:1)

char answer[2];包含仅2个字节的空间。 (在NUL终止字符串的情况下,1字节+ 1 NUL个字符)

CC++访问超出数组大小的数据undefined。所以你现在应该问whyhow等等。你应该不这样做。

处理这种未定义行为的正确方法是:

  • 在C中在内存中分配足够的空间(或者使用fread不要读取足够的空间 数组可以消化的空间)
  • 在C ++中,使用std::string