为什么结果如此不同?

时间:2015-02-24 18:16:55

标签: c++

我不知道为什么类似的代码有很大的不同?第一个代码正常输出,但第二个代码输出一些无法识别的字符。谁能为我解释一下?

THKS

#include <iostream>

using namespace std;

int main(){

    char a[5] = { 'A', 'B', 'C', 'D' };

    cout << a + 1 << endl;

    char b[5] = {'a','b','c','d','e'};
    cout << b+1 << endl;
    return 0;
}

3 个答案:

答案 0 :(得分:11)

表达式a+1b+1都会降级为char*,然后<<将其视为以NUL结尾的字符串,但只有a是NUL封端的。访问b作为NUL终止的字符串会导致未定义的行为,在您的情况下,似乎是在前几个字符后打印垃圾。 (注意,我最初说两者都不是NUL终止的,但后来我注意到a的初始值设定项中只有4个字符,但指定的大小为5.这意味着第5个元素将被零初始化,实际上是NUL终止a。)

如果要正确打印它们而不会导致未定义的行为,请确保它们是NUL终止的:

int main(){

    char a[5] = { 'A', 'B', 'C', 'D' }; // Works as-is, but not good form

    cout << a + 1 << endl;

    char b[6] = {'a','b','c','d','e', '\0'}; // Needed NUL-terminated, but still not the best way
    cout << b+1 << endl;
    return 0;
}

或者作为评论中提到的eigenchris,你可以依靠编译器通过使用字符串常量NUL来终止它:

char a[] = "ABCD";
char b[] = "abcde"; // Probably the best way to do this.

答案 1 :(得分:3)

由于您向char *发送cout个参数,例如ab,因此需要使用c样式字符串。这意味着每个字符串也需要零终止字符。所以以下内容将起作用:

char a[5] = { 'A', 'B', 'C', 'D', '\0' };
cout << a + 1 << endl;

char b[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
cout << b + 1 << endl;

b发生的事情是你通过定义所有5个字符来覆盖零字符。 0应该是第六个字符。

答案 2 :(得分:-1)

当你cout << a+1时,输出将为“BCD”,因为'D'后面的字符是一个nul(\0)。
这是因为您指定的数组大小为5,但只给它4个值。剩余的未指定值将设置为0。

当您cout << b+1时,您将获得"bcdeXXXX",这将持续到找到一个零。
(基于内存中的内容,XXX将是不可预测的字符。)

这是因为您指定了所有5个字符的值,并且未定义超出该字符的内存。它可能是nuls,它可能是早期程序遗留下来的随机值。没有办法确切知道。但cout将继续打印,直到遇到空\0,或者通过读取无法访问的内存地址导致分段/访问冲突。

这就是你在第二个输出上得到随机垃圾的原因。