C++中扫描数组时已读取的变量n被意外修改是什么原因?
C++变量n被意外修改的问题分析
- 第一处错误是变量声明顺序错误:你在
n还未被赋值的情况下就声明了变长数组arr[n]。此时n是未初始化的局部变量,存储的是栈上的随机垃圾值,数组arr的长度是基于这个随机值确定的,后续你通过scanf给n赋值为4并不会改变已经声明的arr的长度。 - 第二处错误是使用了非标准C特性:变长数组(VLA)是C99的标准特性,C标准从未支持该用法,仅部分编译器(如GCC)通过扩展支持,其行为本身就没有标准保障。
- 最终导致n被修改的直接原因是栈缓冲区溢出:如果声明时
n的随机值小于4,那么arr的实际长度小于4,你循环给arr[0]~arr[3]赋值时就发生了数组越界。局部变量n和arr都存储在栈空间上,越界写入的数组元素刚好覆盖了n对应的内存地址,而你最后一次写入的元素值是2,所以n的值就被意外改成了2。
修复方案
写法1(符合C++标准,兼容性最好,推荐)
使用标准库vector存储数组,无需依赖编译器扩展:
#include <cstdio> #include <vector> using namespace std; int main() { int n; scanf("%d", &n); vector<int> arr(n); // 先确定n的值,再初始化vector printf("%d \n", n); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); printf("%d ", arr[i]); printf("n=%d ", n); } printf("\n%d", n); return 0; }
写法2(仅支持带VLA扩展的编译器)
调整变量声明顺序,先读取n的值,再声明变长数组:
#include <cstdio> using namespace std; int main() { int n; scanf("%d", &n); // 先给n赋值 int arr[n]; // 再声明变长数组 printf("%d \n", n); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); printf("%d ", arr[i]); printf("n=%d ", n); } printf("\n%d", n); return 0; }
内容的提问来源于stack exchange,提问作者Ruadh Mac Cárthaigh
相关产品推荐
相关产品推荐

