c语言数组的数量可以是变量吗(数组长度可以是变量吗)
c语言数组的数量可以是变量吗(数组长度可以是变量吗)
2024-11-22 09:34:01  作者:一个限量版  网址: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-11-22真心换真心的经典句子一、如果彼此出现早一点,也许就不会和另一个人十指紧扣又或者相遇的再晚一点,晚到两个人在各自的爱情经历中慢慢地学会了包容与体谅善待和妥协也许走到一起的时候,就不会那么轻易地放弃,任性地转身,放走了爱情没。
  • 韦德哈斯勒姆白敬亭投篮比拼(就是灌篮韦德教白敬亭迷踪步)
  • 2024-11-22就是灌篮韦德教白敬亭迷踪步中新网9月20日电上周,由优酷出品、阿里体育联合出品、优制娱乐承制的《这!就是灌篮》36强诞生,他们将在本周上演“组队抢人大战”,迎接本季节目首场5v5全场赛经过休整,王少杰伤愈“王者归来”重振黑马班。
  • 欧妹吃蛋(欧妹被摸肚好爽 见镜头埋脸甩手)
  • 2024-11-22欧妹被摸肚好爽 见镜头埋脸甩手实习记者曾佩瑄/采访报导台中市2岁大的欧告「阿包」小时候曾在外流浪,还被不少大狗包围、欺负,后来因缘际会下被哥哥带回家,从此产生紧密情感这天阿包见到久违的哥哥回家,被摸肚时虽然一脸镇定,但看到镜头却娇。
  • 电动执行器推力计算 角行程执行器扭矩转推力计算公式及图示
  • 2024-11-22电动执行器推力计算 角行程执行器扭矩转推力计算公式及图示有的客户问角行程执行器带动调节阀、套筒阀是如何选型的首先必须知道阀门的通经、阀前、阀后压力,从而得知拉动阀门需要的推力根据这个推力大小来倒推计算出所需角行程执行器的扭矩大小首先看图示:下图通过上图可清。
  • 白酒能上地铁吗(不是所有随行物品都可以进地铁)
  • 2024-11-22不是所有随行物品都可以进地铁白酒可以带上地铁最多能带2000毫升,也就是4斤液体应该拎在手中(不要装在包裹内);两公斤以内的白酒(未开封瓶装)可以通过安检;超过两公斤可以跟朋友分别携带;超过两公斤将被劝离白酒易燃,属于不是特别安。
  • 教你红烧茄子怎么做(正宗的红烧茄子怎么做)
  • 2024-11-22正宗的红烧茄子怎么做要说茄子怎么做最好吃,当仁不让必是这道红烧茄子!红烧茄子是一道历史久远的特色佳肴,汤汁调味很厚重却又不会抢了茄子的风头,口感鲜香适口,外酥里嫩,味美多汁只可惜小编家里人口味清淡,没法从奶奶手上继承这道。
  • 初二物理第二章声现象知识点(物理在线课堂初二声现象)
  • 2024-11-22物理在线课堂初二声现象复习要点总结:一、声现象1、在复习过程中学习思维方式提高思维能力:为什么、逆向思维、如何……2、人耳听到声音需要满足五个条件:发声体在振动、有传播声音的介质、发声体振动的频率在人耳的听觉频率范围之内、。
  • 爱你就像爱月亮歌词(爱你就像爱月亮歌词完整版)
  • 2024-11-22爱你就像爱月亮歌词完整版《爱你就像爱月亮》歌词:女:遥望着你住的城市方向总有种莫名难言的感伤泪水不由自主流满脸庞多少的思念在心里疯长男:自从你走进了我的心房我的世界就改变了模样你的一举一动让我痴狂我梦里梦外都在把你想合:爱你。
  • 英雄联盟还有扭曲丛林模式吗(英雄联盟拳头宣布)
  • 2024-11-22英雄联盟拳头宣布大家好,这里是cc聊游戏今天,Riot公布了今年也将会是扭曲丛林的最后一年,在今年之后扭曲丛林将要像之前的统治战场一样和我们说再见了那么,你还记得这个3V3地图里的最强野怪——卑鄙之喉吗?你有没有击杀。
  • 郭靖宇新戏南洋女儿情救场 郭靖宇小娘惹地方台先播
  • 2024-11-22郭靖宇新戏南洋女儿情救场 郭靖宇小娘惹地方台先播文\娱铺子郭靖宇《小娘惹》地方台先播,很虐但很吸睛,打破观众原版滤镜《小娘惹》由郭靖宇担任总导演和监制,洪荣狄编剧,肖燕、寇家瑞、岳丽娜、戴向宇等联袂主演的年代剧《小娘惹》正在东方影视频道(原上海电视。
  • 暑假实践活动分享(暑期实践篇七看了才知道)
  • 2024-11-22暑期实践篇七看了才知道看了才知道原来留守儿童李紫茉是多么地渴望温暖与关怀原来粗茶淡饭的生活也可以过的如此开心与满足原来维修电脑也有别样的快乐原来古墓挖掘真的不容易原来……暑期实践是那么的美好!资源环境与旅游学院“安濮携手,。
  • 白菜纯素馅饺子怎么调馅(不要用盐杀水或者焯水)
  • 2024-11-22不要用盐杀水或者焯水导语:调白菜馅,不要用盐杀水或者焯水,巧用一招,饺子好吃还营养高在过去想吃顿饺子没有那么容易,只有过年过节或者庆祝什么的时候才会包饺子,现在日子好了,饺子经常活跃在我们的餐桌上,只要心情好随时都可以吃。