c语言数组的数量可以是变量吗(数组长度可以是变量吗)
c语言数组的数量可以是变量吗(数组长度可以是变量吗)
2024-09-29 12:14:32  作者:一个限量版  网址:https://m.xinb2b.cn/know/znz370444.html

关于C 数组提出几点问题:先看下这两段代码,今天小编就来说说关于c语言数组的数量可以是变量吗?下面更多详细答案一起来看看吧!


c语言数组的数量可以是变量吗

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

预备

先看下这两段代码

变量作为数组的长度可行吗?

#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 6sizeof array 24array[0] 20

访问超过长度的数组下标的值会发生什么?

#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 40array[3] 1array[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 0x7ffeb675f418func4b address 0x7ffeb675f420func4c address 0x7ffeb675f41cfunc3a address 0x7ffeb675f3c8func3b address 0x7ffeb675f3d0func3c address 0x7ffeb675f3ccfunc2a address 0x7ffeb675f378func2b address 0x7ffeb675f380func2c 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 0x7ffff2c76568func4b address 0x7ffff2c76570func4c address 0x7ffff2c7656cfunc3a address 0x7ffff2c76510func3b address 0x7ffff2c76360func3c address 0x7ffff2c76514func2a address 0x7ffff2c76328func2b address 0x7ffff2c76330func2c address 0x7ffff2c7632c

func4a - func3a = 88func3a - func2a = 488从上面两段代码其实可以看出C 是支持变量长度的数组的,说不支持的那是很古老的编译器,在如下链接中也可以找到答案。https://c-for-dummies.com/blog/?p=3488https://www.drdobbs.com/the-new-cwhy-variable-length-arrays/184401444https://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.out100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 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 40array[3] 1array[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,操作超过长度的下标会抛异常有利于开发者及时发现错误。

  • 一个手机两个微信怎么下载(怎么在手机上下载两个微信)
  • 2024-09-29怎么在手机上下载两个微信在手机上找到设置按键,点击打开设置,进入后会看到应用点击进入,在进入应用后,不要下拉,找应用分身,找到后点击进入应用分身在进入应用分身后,就看到了能分身的全部应用,在找到微信后点击后面的分身按钮下点击。
  • 收获的季节也是最美的季节(享受最美的季节)
  • 2024-09-29享受最美的季节这个季节是一个成长的季节,每个孩子的心中都充满着一份期待与感动而我们又一起在这个季节里享受着最美的季节在这个时节,我们这些孩子最开心,最开心的时候,我们会收到这个季节这里灿烂的笑容,收到这些积极的心情。
  • 中外轮胎测试对比(硬碰硬-中美欧日韩轮胎对抗测评)
  • 2024-09-29硬碰硬-中美欧日韩轮胎对抗测评这里是轮胎商业的第72次专业测评,本次测评为大家带来的是分别来自中国、德国、日本、美国以及韩国轮胎制造商5款王牌产品,它们分别是:●玲珑GRIPMASTERC/S(CS820)●德国马牌UltraCo。
  • 日照旅游两天一夜详细旅游攻略(清明假期到日照旅游)
  • 2024-09-29清明假期到日照旅游山东省日照市是一个美丽的海滨旅游城市,位于山东东南部,北连青岛南接江苏连云特的地理位置,造就了日照宜人的气候,冬无严寒,夏无酷暑,吸引了全国各地的游客到日照旅游度假那么清明假期到日照旅游,不能下海游泳。
  • a站b站c站e站f站g站什么意思(互联网的世界你知道B站)
  • 2024-09-29互联网的世界你知道B站这里是知科技app,如果觉得本文有用,欢迎点赞【关注】我往期精彩回顾:如何长时间保存重要数据?拒绝U盘,拒绝网盘A站AcFun,简称“A站”,创办于2007年6月,是中国大陆第一家弹幕视频网站,其灵感。
  • 多层实木地板和强化复合地板区别(实木地板多层地板)
  • 2024-09-29实木地板多层地板地板和地砖都是常见的地面装饰材料相比较于地砖的冷硬,地板凭借其舒适的脚感和温润的肌理,更受大众青睐,成为卧室等空间最常用的地面装饰材料目前市面上常见的地板种类有实木地板、多层实木地板以及强化地板,这三。
  • 吃羊肉喝什么酒好(吃羊肉搭配什么酒最好)
  • 2024-09-29吃羊肉搭配什么酒最好葡萄酒羊肉味甘而不腻,性温而不燥,具有补肾壮阳、暖中祛寒、温补气血、开胃健脾的功效,所以冬天吃羊肉,既能抵御风寒,又可滋补身体,实在是一举两得的美事尤其是吃羊肉喝葡萄酒很般配在西餐中羊肉属于红肉,通常。
  • 名侦探柯南最经典的几个情节 名侦探柯南中最让人难忘的8句话
  • 2024-09-29名侦探柯南最经典的几个情节 名侦探柯南中最让人难忘的8句话《柯南》作为影响我最深的漫画之一,里面感动过我的台词真的非常多啊~青山透过这些台词传达出的三观也非常的正,下面让我举一些我印象最深的例子吧~1.我从来不知道人杀人的理由,但是人救人是不需要理由的—。
  • 文件夹是怎么使用的(文件夹还能这么用)
  • 2024-09-29文件夹还能这么用天天使用的“文件夹”以下你都会不会?01.快速打开“文件资源管理器”通过【WinE】快捷键快速打开文件夹,再也不要用鼠标拖来拖去了,同学同事都觉得你是个电脑高手呢~02.快速访问设置不想默认打开“文件。
  • 儿童经典名著(经典名著一分钟麦琪的礼物)
  • 2024-09-29经典名著一分钟麦琪的礼物以打工为生的吉姆,靠着微薄的收入养活着自己的爱妻黛拉,眼看着明天就是圣诞节了,掌握着家中经济大权的黛拉,想从可怜的生活费中挤出点钱来给吉姆买份圣诞礼物,可积赞了几个月,只从买菜的钱里挤出了一块八毛七,。
  • 君子上达小人下达是什么意思(君子上达小人下达的解释)
  • 2024-09-29君子上达小人下达的解释君子上达小人下达意思是:意思是君子向上,通达仁义;小人向下,追求名利出处:春秋时期孔子的《论语·宪问》原文节选:子曰:“古之学者为己,今之学者为人”蘧伯玉使人于孔子,孔子与之坐而问焉曰:“夫子何为?”。