c语言数组的数量可以是变量吗(数组长度可以是变量吗)
c语言数组的数量可以是变量吗(数组长度可以是变量吗)
2024-11-05 09:16:39  作者:一个限量版  网址:https://m.xinb2b.cn/tech/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-11-05回眸一笑百媚生的意思介绍回眸一笑百媚生释义:原句为“回眸一笑百媚生,六宫粉黛无颜色”该诗句是用来形容杨贵妃(杨玉环)的端庄美丽出处:唐·白居易《长恨歌》:“回眸一笑百媚生,六宫粉黛无颜色”注释:她回头嫣然一笑,百般娇媚同时显。
  • 高压锅小米地瓜粥的做法(双色小米地瓜粥的做法)
  • 2024-11-05双色小米地瓜粥的做法适合8+宝宝食用想学辅食的宝妈可以加我微信每天都有分享宝宝辅食Y1046224396红薯可补脾益胃,生津止渴,预防宝宝便秘,益气生津,润肺滑肠,小米具有防治消化不良的功效小米还具有防止泛胃、呕吐的功效。
  • 宝宝辅食高铁食物有哪些(如何给宝宝选择高铁类辅食)
  • 2024-11-05如何给宝宝选择高铁类辅食辅食容易引起过敏、腹泻等问题吃辅食,奶量自然会相应减少,但母乳的营养价值比辅食好因为过早给宝宝吃成人食物可能会影响宝宝的发育在这个宝宝的换食期,最好准备一份宝宝食谱,防止过量的钠引起宝宝的高血压,或者。
  • 小学考试必考的九个问题(这些小学题目80的孩子会做错)
  • 2024-11-05这些小学题目80的孩子会做错在考试中,作为出题老师有时候都会出一些看似很简单,但是孩子一做就错,试卷发下来才后悔莫及,今天收集这些类型的题目分享给大家,希望孩子在期末考试中,别再犯这些错了例题一:可能很多人第一眼答案就是正确的,。
  • 阎鹤祥脱口秀吐槽大会完整版(阎鹤祥老师吐槽大会决赛)
  • 2024-11-05阎鹤祥老师吐槽大会决赛在决赛之前,看到路透图阎老师与一位“搭档”穿着大褂站前排,后面还站了两排穿大褂的助演由于脸部打了马赛克,我还猜想是不是德云社的师兄弟来了?这排面是来收购笑果的吧?决赛播出,完全颠覆了我的想象“搭档”是。
  • 马驹长到几个月能骑(新疆汗血马迎来出生旺季)
  • 2024-11-05新疆汗血马迎来出生旺季阿不力米提·沙吾提和兽医马树勇忙着为黑色马驹体检王小军摄阿不力米提·沙吾提和兽医马树勇忙着为黑色马驹体检王小军摄中新网乌鲁木齐2月18日电(记者王小军)进入2月以来的几乎每个清晨,新疆野马集团马医院院。
  • 骨质疏松有这几种症状(骨质疏松的四大症状)
  • 2024-11-05骨质疏松的四大症状最近总是有粉丝问我,骨质疏松的症状是什么,发现不知道的粉丝有很多,特地写一篇给大家骨质疏松症是一种常见于老年人群体的疾病,是一种骨骼退化的全身性疾病比起健康的骨骼,骨质疏松症患者的骨骼骨量低,骨组织微。
  • 西伯利亚有多少个民族(西伯利亚为啥叫西伯利亚)
  • 2024-11-05西伯利亚为啥叫西伯利亚提示:可以看得出来,在莫斯科公国建立之前,中国的北方草原上基本没有俄罗斯人的什么事,而俄罗斯东扩也发生第一位沙皇加冕之后想都能够想得出来,这之前生活在西伯利亚的人们,不可能让这片广阔的区域没有名字所以。
  • 清明荠菜煮鸡蛋的习俗(农历三月三荠菜花煮鸡蛋)
  • 2024-11-05农历三月三荠菜花煮鸡蛋小时候每年清明除了看龙舟赛,外婆会煮荠菜花鸡蛋给我们小孩儿吃说吃的对身体好小朋友也不知道这个是什么东西长大了,知道这个是荠菜花清明节前后荠菜开花了,荠菜花煮鸡蛋有健脾清热的作用所以民间有农历“三月三,。
  • 百家姓出炉了(值得收藏百家姓)
  • 2024-11-05值得收藏百家姓《百家姓》是一部关于中文姓氏的作品按文献记载,成文于北宋初原收集姓氏411个,后增补到504个,其中单姓444个,复姓60个《百家姓》采用四言体例,对姓氏进行了排列,而且句句押韵,虽然它的内容没有文理。