【问题标题】:Why does a char string of n length in c++ always have a null char on [n] index as garbage? [duplicate]为什么 c++ 中长度为 n 的字符字符串在 [n] 索引上总是有一个空字符作为垃圾? [复制]
【发布时间】:2016-11-09 07:05:33
【问题描述】:

在声明一个长度为n的char数组时,[n]处的值总是0,不应该是垃圾值吗?

代码

#include <stdio.h>

int main() {
    char arr[3];
    arr[0] = 'a'; arr[1] = 'b'; arr[2] = 'c';
    // Here arr[3] can be any garbage value.
    // But it always appears to be 0. Why?

    // Also arr[4], arr[5], arr[6]... are not 0,
    // just some garbage as expected

    printf("i\tch  ascii\n");
    int i;

    for(i = 0; arr[i] != 0; i++) //Always breaks at i=3
        printf("%d\t%c\t%d\n", i, arr[i], (int) arr[i]);
    int more = i + 5;
    for(; i<more; i++)
        // I am intentionally going outside the bound
        printf("%i\t%c\t%d\n", i, arr[i], (int) arr[i]);
    return 0;
}

预期输出

你认为输出会是什么?你可以假设:

i   ch  ascii
0   a   97
1   b   98
2   c   99
3   N   78  ----> (This may or may not be 0)
4   �   -103
5   N   78
6   �   -125
7   �   -100

实际输出

i   ch  ascii
0   a   97
1   b   98
2   c   99
3       0  ----> (Why is this always 0?)
4   �   -103
5   N   78
6   �   -125
7   �   -100

注意:int/double/float 数组不会发生这种情况。

【问题讨论】:

  • 你想写ara[i]!='\0'而不是i!='\0'吗?
  • 巧合。
  • 思想实验:拿一副纸牌,把它们扔到地上。将脚放在一张卡片上。抬起你的脚,看看它是什么。再次将脚放在卡片上。如果下次抬脚时看到同一张卡片,您会感到惊讶吗?

标签: c++ c arrays string pointers


【解决方案1】:

您的数组中没有空终止符。 printf 读完它的结尾。这是 c++ 标准未定义的行为。它以ara[4] 结尾,因为你(不)幸运。它可以走得更远甚至让你的程序崩溃,因为它应该做的是undefined

为了合理化停在ara[4]:在你的缓冲区后面的那个位置可能有一个\0 字符

【讨论】:

  • ara[4] 结尾并不是那么幸运,因为理论上它可能在映射内存区域之外(即导致总线故障)。幸运的是,阅读ara[4] 并没有发生内存访问违规(或者实际上并不是那么幸运,因为此后没有立即意识到问题,任由自己摆布调试会话之神)。
  • @barakmanos,我怀疑它最终可能会超出映射的内存区域。有托管环境保存在堆栈帧上的数据需要考虑。但是,是的,“工作”而不是崩溃和燃烧是不吉利的。
  • “要考虑的由托管环境保存在堆栈框架上的数据” - 这是特定于平台的(无论如何,不​​是由语言标准规定的)。例如,假设您在裸机上运行(即,没有操作系统、没有虚拟内存、没有线程和进程),并且恰好在某个时间点在堆栈末尾分配了该数组当函数被调用时。顺便说一句,这个数组很可能分配在数据部分,而不是堆栈中(即全局和/或静态)。 OP没有具体说明这一事实。但同样,这不是由语言标准规定的。
  • @barakmanos,合理化 UB 是徒劳的。所以我用更少的关于 OPs 代码的假设来改写它。你的任何一点或我原来的解释都是正确的。
  • 我并没有试图合理化它。我只是暗示“它以ara[4] 结尾,因为你很幸运”,实际上你是在试图自己合理化它,因为这并没有太多的运气。无论如何,我想这更像是一场哲学辩论,所以......
【解决方案2】:

你对i=='\0'的期望如何 只需迭代到数组大小或将字符值与 '\0' 进行比较。由于内存中的垃圾值,您获得的随机索引。

【讨论】:

  • 这不是垃圾,是未指定的。
  • 是的,它未定义,可能导致 UB
【解决方案3】:

您的实现很可能将局部变量布置为

  • ara - 3 个字节
  • 填充 - 1 个字节
  • i(或其他一些局部变量)。

因此,当您到达ara 的末尾并进入未定义行为时,结果仍然是相当确定的(但如果您使用不同的编译器,可能会发生变化)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    相关资源
    最近更新 更多