关于C++数组提出几点问题:

预备

先看下这两段代码

  1. 变量作为数组的长度可行吗?
#include <iostream>
using namespace std;void func(int num) {int array[num]; // num > 0cout << "num " << num << endl;cout << "sizeof array " << sizeof(array) << endl;array[0] = 20;cout << "array[0] " << array[0] << endl;
}int main() {func(6);return 0;
}

输出:

num 6
sizeof array 24
array[0] 20

  1. 访问超过长度的数组下标的值会发生什么?
#include <iostream>
using namespace std;void func() {int array[10];array[3] = 1;array[20] = 3;cout << "sizeof array " << sizeof(array) << endl;cout << "array[3] " << array[3] << endl;cout << "array[20] " << array[20] << endl;
}int main() {func();return 0;
}

输出:

sizeof array 40
array[3] 1
array[20] 3

分析

首先分析问题1,我们平时看书学习过程中总看见说C++的数组长度一定要是常量且不能是变量,很多资料需要在编译期确定栈帧的大小,如果是变量就不能在编译器确定栈帧大小,但上述代码为什么可以正常运行呢?光看不如实践,先看这样一段代码:

#include <iostream>
using namespace std;void func2() {int a;int b[4];int c;cout << "func2a address " << &a << endl;cout << "func2b address " << &b << endl;cout << "func2c address " << &c << endl;// func1();
}void func3(int num) {int a;int b[4];int c;cout << "func3a address " << &a << endl;cout << "func3b address " << &b << endl;cout << "func3c address " << &c << endl;func2();
}void func4(int num) {int a;int b[4];int c;cout << "func4a address " << &a << endl;cout << "func4b address " << &b << endl;cout << "func4c address " << &c << endl;func3(num);
}int main() {func4(5);return 0;
}

输出:

func4a address 0x7ffeb675f418
func4b address 0x7ffeb675f420
func4c address 0x7ffeb675f41c
func3a address 0x7ffeb675f3c8
func3b address 0x7ffeb675f3d0
func3c address 0x7ffeb675f3cc
func2a address 0x7ffeb675f378
func2b address 0x7ffeb675f380
func2c address 0x7ffeb675f37c

再看这段代码:

void func2() {int a;int b[4];int c;cout << "func2a address " << &a << endl;cout << "func2b address " << &b << endl;cout << "func2c address " << &c << endl;// func1();
}void func3(int num) {int a;int b[num];int c;cout << "func3a address " << &a << endl;cout << "func3b address " << &b << endl;cout << "func3c address " << &c << endl;func2();
}void func4(int num) {int a;int b[4];int c;cout << "func4a address " << &a << endl;cout << "func4b address " << &b << endl;cout << "func4c address " << &c << endl;func3(num);
}int main() {func4(100);return 0;
}

输出:

func4a address 0x7ffff2c76568
func4b address 0x7ffff2c76570
func4c address 0x7ffff2c7656c
func3a address 0x7ffff2c76510
func3b address 0x7ffff2c76360
func3c address 0x7ffff2c76514
func2a address 0x7ffff2c76328
func2b address 0x7ffff2c76330
func2c address 0x7ffff2c7632c

func4a - func3a = 88

func3a - func2a = 488

从上面两段代码其实可以看出C++是支持变量长度的数组的,说不支持的那是很古老的编译器,在如下链接中也可以找到答案。

https://c-for-dummies.com/blog/?p=3488

https://www.drdobbs.com/the-new-cwhy-variable-length-arrays/184401444

https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard

备注:尽管C++目前支持变量长度的数组,但是不建议使用,因为数组使用的是栈内存,栈内存是有大小限制的,一般是8192字节,既然长度是变量,那就可能是任何值,就有可能超过8192,这样就会stack overflow,所以动态内存最好使用堆内存。

再分析问题2:操作超过数组长度的内存会发生什么?看下面这段代码:

#include <iostream>
using namespace std;void func() {int array[10];array[3] = 1;array[40] = 3;cout << "sizeof array " << sizeof(array) << endl;cout << "array[3] " << array[3] << endl;cout << "array[40] " << array[40] << endl;
}int main() {int a[200];for (int i = 0; i < 200; ++i) {a[i] = 100;}for (int i = 0; i < 200; ++i) {cout << a[i] << " ";}cout << endl << "=====================" << endl;func();cout << "=====================" << endl;for (int i = 0; i < 200; ++i) {cout << a[i] << " ";}cout << endl << "=====================" << endl;return 0;
}

输出:

root@3eaa9392a3d9:/ubuntu/test_dir# ./a.out
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
=====================
sizeof array 40
array[3] 1
array[40] 3
=====================
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 3 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
=====================

看代码输出,在函数内操作超过数组长度的内存没有什么影响,但是它却导致了上一级的数组a[200]里的内容被改变,因为数组使用的是栈内存,经过问题1的代码输出以及分析可以看出,栈帧内存是向下增长的,代码中操作了超过数组长度的内存地址,就影响到了之前栈帧的内存数据,导致之前栈内存数据出现错误,可能就会引发大bug。

总结

C++中数组长度可以是变量,但是不建议使用,因为数组使用的是栈内存,变量可以是个比较大的数,这样会导致stack overflow,建议使用堆内存。

操作超过数组长度的内存可以编译通过且表面上看不出来问题,但是会导致栈内存出现脏写,最终可能会引发难以排查的bug,建议数组使用std::array,操作超过长度的下标会抛异常有利于开发者及时发现错误。 更多文章,请关注我的V X 公 主 号:程序喵大人,欢迎交流~

函数的参数可以是数组吗_C++数组长度可以为变量吗?相关推荐

  1. java 结构体数组初始化_C数组结构体联合体快速初始化

    背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元 ...

  2. C语言 数组在定义时长度不能用变量

    问题描述 在数组定义的时候,括号中定义数组长度使用的是整形变量,在dev c++和codeblocks上编译后,没有显示语法错误.但是在普通的oj提交平台上测试后显示语法错误. int n; scan ...

  3. JavaScript简餐——细看函数的参数

    文章目录 前言 一.理解参数 二.箭头函数中的参数 三.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript高级程序设计(第4版)> ...

  4. 求一个二维数组外围元素之和_C++数组作为函数的参数(学习笔记:第6章 04)...

    数组作为函数的参数[1] 数组元素作实参,与单个变量一样. 数组名作参数,形.实参数都应是数组名(实质上是地址,关于地址详见后续章节),类型要一样,传送的是数组首地址.对形参数组的改变会直接影响到实参 ...

  5. 数组作为函数的参数传参时,数组名会退化为指针

    1.数组作为函数的参数传参时,数组名会退化为指针 数组作为函数的参数传参时,数组名会退化为指针,数值传参时,需要把数值的长度一起传过去,另外,sizeof()运算符包含字符串的哨兵'/0',而strl ...

  6. c c++ 函数内数组初值_C/C++函数指针与指针函数

    关于指针,前面文章C语言指针详解有过介绍,这里主要讨论函数指针和指针函数. 1 什么是指针? 定义:指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量; 上面一个 4GB 的内存可以存放 ...

  7. php数组实现堆栈的三个函数,while,do while,s函数的参数作用域,数组堆栈,常见的数组函数等学习2018/8/23...

    1,while do while 使用 实例 /** * while 和do while使用 */ $sum=0; $i=0; while ($i<=100) { $sum=$sum+$i; $ ...

  8. C语言-二维数组做函数的参数

    文章目录 1 引例 2 观点1 这种使用方法是错误的 3 观点2 根本不需要这么做 4 二维数组做函数参数的方法 4.1 方法1 4.2 方法2 4.3 方法3 5 与Java的不同 1 引例 下面的 ...

  9. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  10. 函数中参数有数组时注意的小问题(不一定要传递数组长度,不用返回数组,可以在函数中改变数组元素值)

    函数中参数有数组时注意的小问题: 1.不一定要传递数组长度 2.不用返回数组,可以在函数中改变数组元素值 通过下面这个小例子来验证: #include<iostream> #include ...

最新文章

  1. 【新周报(045)】青少年编程竞赛交流群周报
  2. HALCON No finder pattern could be found错误解决
  3. python【数据结构与算法】内置函数 zip() 函数(看不懂你来打我)
  4. pytorch模型的保存与加载
  5. java.lang.IllegalArgumentException: Receiver not registered
  6. 第十二届蓝桥杯大赛软件赛省赛第二场【C++B组】
  7. 所有受限制的应用程序包_【译】使用Blazor构建桌面应用
  8. Android应用开发——service连接泄露异常:android.app.ServiceConnectionLeaked: that was originally bound here
  9. 信息学奥赛一本通C++语言——1002:输出第二个整数
  10. Java连接GreenPlum
  11. iscsi:IO操作流程(一)
  12. 10款屏幕取色器/颜色拾取工具软件介绍及下载地址
  13. 树莓派linux虚拟键盘,树莓派raspbian安装matchbox-keyboard虚拟键盘
  14. icp许可证申请:一文读懂icp许可办理流程、费用
  15. 没学历,当程序员还有机会吗?
  16. 2分钟定制自己的专属桌面——win10仿Mac os风格美化!
  17. 基于某知名招聘网站的上海财务岗位数据分析(含excel可视化)
  18. springmvc中拦截器
  19. 在系统grub.cfg里面设定关闭 aspm
  20. jQuery 操作整理

热门文章

  1. 【TSP】基于matlab GUI模拟退火算法求解旅行商问题【含Matlab源码 1083期】
  2. 【元胞自动机】基于matlab元胞自动机交通流仿真【含Matlab源码 827期】
  3. 【语音去噪】基于matlab低通+自适应滤波去噪【含Matlab源码 352期】
  4. 【手写字母识别】基于matlab GUI BP网络手写体大写字母识别【含Matlab源码 183期】
  5. 【机械仿真】基于matlab GUI机械臂运动控制【含Matlab源码 063期】
  6. pandas的基本函数
  7. 电脑qq浏览器怎么滚动截长图_电脑怎么快速截图?
  8. python2.7 安装第三方库
  9. 数论 欧几里德算法
  10. vue中 点击事件的写法_Vue父子组件状态同步的最佳方式