美文网首页C++精进之路
C++数组长度可以为变量吗?

C++数组长度可以为变量吗?

作者: this_is_for_u | 来源:发表于2020-04-30 21:55 被阅读0次

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

预备

先看下这两段代码

  1. 变量作为数组的长度可行吗?
#include <iostream>
using namespace std;

void func(int num) {
    int array[num]; // num > 0
    cout << "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++数组长度可以为变量吗?

    关于C++数组提出几点问题: 预备 先看下这两段代码 变量作为数组的长度可行吗? 输出: 访问超过长度的数组下标的...

  • C++数组长度可以是变量吗

    关于C++数组提出几点问题: 预备 先看下这两段代码 变量作为数组的长度可行吗? 输出: 访问超过长度的数组下标的...

  • c++零碎问题记录

    2020年3月6日,正式开始学习C++。记录leetcode上遇到东西; 1.C++使用变量作为数组长度 数组长度...

  • C++ 数据结构与算法

    C++ 容器与算法 vector 容器: 动态数组,可动态扩容,扩容时重新开辟原有长度2倍的长度,然后将原有的数据...

  • C++面试再进阶

    1、C++定义数组有大小限制吗?如何定义一个长度为一百万的数组? 答:定义数组大小的限制主要是看数组定义在内存的哪...

  • C++面试再进阶

    1、C++定义数组有大小限制吗?如何定义一个长度为一百万的数组? 答:定义数组大小的限制主要是看数组定义在内存的哪...

  • c++数组初始化问题

    1、数组的长度是常量 int aa[20] = {}; bool bb[30] = {}; 2、数组的长度是变量 ...

  • Android NDK开发之旅20--C++--结构体

    Android NDK开发之旅 目录 C++ 结构体 C/C++ 数组允许定义可存储相同类型数据项的变量,但是结构...

  • JS中各种遍历方法

    数组遍历方法 for循环 (★★★☆☆) 使用临时变量,将长度缓存起来,避免重复获取数组长度,当数组较大时优化效果...

  • Java数组类型

    数组类型和数组引用变量详解 数组类型为什么要用数组?Java数组的两大特征:定义数组时,不能指定数组的长度变量分为...

网友评论

    本文标题:C++数组长度可以为变量吗?

    本文链接:https://www.haomeiwen.com/subject/gycxghtx.html