查余补漏:
在前几次的讲解中,有朋友提出C语言的内存分配只是malloc和free,然后还有在缓存章节的有朋友提出的内存四区,所以我在说数组之前,先进行补漏。
我们前面在说内存分配的时候,并没有明确的说明内存四区的问题,因为内存分配是从内存实际应用中提出的分配模式,而内存四区却是C语言中的内存模型,其中代码区和我上期写的缓存,在我看来,缓存是CPU中单独的一个模块,而代码区却是在编译完成后,就不变化的一块内存区域。从C语言内存四区角度来看,内存分配中的malloc和free只是内存四区中堆的操作,所以这朋友观点就有点错误。后面在缓存文章里提出内存四区,可能是这位朋友把缓存和内存混为一体了,虽然缓存我们说是内存中预留出的一块区域,但是这只是从虚拟内存角度来说,从CPU角度来说,缓存是内存与CPU之间的一个临时储存器,其读取速度要比内存快的多,所以缓存并不是内存四区的一部分。
C语言学习
数组:
数组的概念是一组数据的集合,我们称为数组。
学过解释型的脚本语言的朋友可能知道,在大多数情况下,我们在使用数组的时候,往往都会使用可变数组,因为使用起来比较方便,所以很多朋友在重新拿起C语言,使用数组的时候往往会出现越界、内存溢出等现象,其原因就是C语言的数组是静态的。
既然知道了C语言数组是静态的,为什么在网上会出现使用malloc申请动态数组的案例,这时候我们就要说说堆和栈,编译前和编译后的问题了。
一般情况下,我们在使用一个数组的时候必须指定其长度和类型,主要目的是为了让计算机明确使用了多大的内存空间。比如我们申请一个需要存放四个int类型的数组,那么就会申请一个长度为16自己的内存空间,由于这部分空间是系统自动分配的,所以它应该储存在栈区,而且长度是固定的,所以我们在存入第5个数字的时候就会出现内存溢出,因而说明C语言数组在定义之后长度不能增加,也不能减少,所以我们称之为静态数组。
在这里我就不得不说一个有趣的知识点,那就是C语言的检查系统,为了保证C语言的速度和灵活,C语言在编译期间不会对数组的越界进行检查,所以会发现,为什么编译通过了而运行时会出错,说明了点,中层干部将自己要干的活推给了下属,结果下属在工作的时候发现它干不了,于是就出现了错误。
变长数组:
由于很多时候,我们经常会遇到不知道数据有多少,所以就无法明确,数组长度,那怎么办呢,于是就有了变长数组,那么这样就可以定义一个适合长度的数组了,但是有个问题是,当我们生成数组后,然后再向里面添加的时候发现,如果数组中数据已经饱和,那么新增的数据就不会出现。
#include int main()
{
int n;
printf("Input string length: ");
scanf("%d", &n); //输入想要的长度int a[n]; //定义变长数组for (int i = 0; i < n; i++)
{
/* code */
a[i] = i;
printf("添加了数字 = %d
",a[i]);
} //将数组添加至饱和a[n+1] = 100; //我们越界增加printf("读取新增的数据 %d
",a[3]);
return 0;
}
那么答案是什么我们运行来看看。
结果是3
从结果来看,变长数组并不能增加数的组长度。由此可见,变长数组仍然是静态数组。从代码上来看,int a[n] 中因为n为变量,所以就成了所谓的变长?
通过malloc定义动态数组
然后我们再说说使用malloc出来的动态数组,我个人称之为假数组。具体原因我们来分析一下,我从网上找了一个出现频率最高的一串代码类型:
#include
int main()
{
int n;
scanf('%d',n);
int *pa = (int*)malloc(sizeof(int)*n);
return 0;
}
很多朋友都以类似的方式在说这样可以申请一个动态数组,我们从代码来看,先定义了 一个int型的n用来表示数组长度,然后用scanf函数等待用户输入一个想要的长度,输入完成后,通过sizeof函数获取int长度,然后乘上我们输入的数字,这样就申请到了我们需要的内存空间。然后将这片内存空间数据类型指定为int,并且将指针指向同为int类型的pa上,这样,我们申请了一个所谓的动态数组,那么我们来试试它是不是动态的。
我们先修改代码如下:
#include
int main()
{
int n;
printf("输入值:");
scanf("输入%d", &n);
int *pa = (int*)malloc(sizeof(int)*n);
for (int i = 0; i < 4; i++)
{
/* code */
pa[i] = i;
printf("取值%d
",pa[i]);
}
return 0;
}
然后测试:我们再输入的时候让数组只有一个数,但是向里面添加的时候,添加4个数。
有四个值
从这里可以看出这样动态的申请数组是可行的,但是具体原理,还是因为使用了指针,指针我们会在后面进行讲解,我这里没有去释放申请的内存,请见谅。
结语:今天我们主要说了静态数组,看了动态数组的申请方式,但是由于动态数组使用了指针方面的知识,所以我们在后面讲到,我们先消化静态数组的特征就好。
这里预留一个问题:
将上面的代码中,for循环的i<4,修改成i<100,看看会出现什么情况,具体原因什么,希望朋友们可以尝试一下。