首页 > 解决方案 > 固定大小的 C++ 数组获取垃圾值

问题描述

我试图将字符串循环旋转 1 个班次。这是简单的代码:

#include <bits/stdc++.h>
using namespace std;

int main() {
  string s = "1010";
  char a[s.length()];
  for (int i = 0; i < s.length() - 1; i++) {
    a[i] = s[i+1];
  }
  a[s.length()-1] = s[0];
  std::cout << a << '\n';
  std::cout << strlen(a) << '\n';
}

当我运行此代码时,我得到以下输出:

aditya@aditya-Inspiron-3558:~/miscCodes$ ./a.out 
0101�
6

我的数组的长度如何变化?由于垃圾值?

标签: c++arraysstring

解决方案


可变长度数组 (VLA)不是标准 C++ 的一部分。阅读更多内容,为什么可变长度数组不是 C++ 标准的一部分?


但是,假设您使用了允许它们的编译器扩展,那么问题是您在这里使用了 C 函数:

std::cout << strlen(a) << '\n';

它需要一个 C 字符串,这意味着一个以NULL 结尾的字符串

这意味着您应该使您的数组足够大以容纳 NULL 终止字符,如下所示:

char a[s.length() + 1];

因为string::length()将为字符串“1010”返回 4。这意味着 C 字符串应该是这样的:“1010\0”,即实际字符串,附加 NULL 终止字符。因此,您需要一个大小为 5 的数组来存储该字符串。

一个简单的解决方法是:

char a[s.length() + 1] = {0};

这将 NULL 初始化数组的每个单元格。然后,您将用字符覆盖它的每个单元格,除了最后一个单元格,专门为 NULL 终止符保留。

另一种方法是仅将 NULL 终止符分配给字符串的最后一个单元格,例如a[s.length()] = '\0';. 注意s.length()现在是数组最后一个元素的索引。


标准 C 字符串函数(如strlen())依赖于 NULL 终止字符来标记字符串的结尾。在没有那个重要角色的情况下,他们不知道何时停止,因此访问超出了他们打算访问的点的内存。

这会调用未定义行为(UB),它在您的计算机中使用垃圾值访问内存。


推荐阅读