一维数组
假如我们要存储1到10的数字,该怎么存储呢?
在C语言中给出了数组的定义:一组相同类型类型的集合
数组定义:
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 9 ,10};//定义一个大小为10的数组,最多放10个元素
一维数组的使用
对于数组的使用,我们来看一段代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> //整型数组,数组的下标是从0开始的 int main(){ int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 9 };/*可以不去写数组的长度,此数组的长度是依据后面的的 数字长度来确定的,但是若打印输出时越界,则所打印的数字 此时便是随机的了*/ int arr[7] = { 1, 2, 3, 4, 5 };//当确认数组长度后,若数组并未放满,则数组剩余默认值为0 int arr1[3];//默认值是随机值,并不是0,输出值为-858993460,-858993460,- 858993460 for (int i = 0; i <= 11; i++) { printf("%d,", arr2[i]);/*此时数组arrr2[0]-arr[7]打印的是1,2,3,4,5,6,7,8,9 而从arr[8] - arr[11]则是随机生成的了,分别为-858993460,19922248,7481961,1*/ } printf("\n"); for (int i = 0; i <= 6; i++) { printf("%d,", arr[i]);//输出数组arr[7] } printf("\n"); for (int i = 0; i <= 2; i++) { printf("%d,", arr1[i]);//输出数组arr1[3] } return 0; }
针对上述代码,我们来进行分析:
int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 9 };/*可以不去写数组的长度,此数组的长度是依据后面的的数字长度来确定的,但是若打印输出时越界,则所打印的数字此时便是随机的了*/
此处我们定义了一个没有数组大小的arr2数组,此处可以不用定义数组的大小,原因是其数组的长度是依据后面的数字长度来确定的,但是若打印输出时越界,则所打印的数字此时便是随机的了。
下面对此数组进行打印输出:
for (int i = 0; i <= 11; i++) { printf("%d\n", arr2[i]);/*此时数组arrr2[0]-arr[7]打印的是1,2,3,4,5,6,7,8,9 而从arr[8] - arr[11]则是随机生成的了,分别为-858993460,19922248,7481961,1*/ }
输出结果为:
此时我们可以看到此时数组arrr2[0]-arr[7]打印的是1,2,3,4,5,6,7,8,9,而从arr[8] - arr[11]则是随机生成的了,分别为-858993460,19922248,7481961,1,即若打印输出时越界,则所打印的数字此时便是随机的了。
int arr[7] = { 1, 2, 3, 4, 5 };//当确认数组长度后,若数组并未放满,则数组剩余默认值为0
此处定义了一个大小为7的整形数组,但是细心的同学会发现数组并没有放满,那么此时若数组并未放满的话,数组剩余的默认值都为0
下面我们来调试下上述代码:
从调试中我们可以看出当数组未放满时,数组剩余默认值都为0,输出结果如下:
int arr1[3];//默认值是随机值,并不是0,输出值为-858993460,-858993460,- 858993460
此处定义了一个大小为3的整形数组,但是并没有给出具体的存储的数值,此时大多数同学会认为此处三个值应该默认都为0,这也是大家最容易犯错的一个点,因为此时默认的值是系统随机给出的,例如此数组的输出结果为-858993460,-858993460,- 858993460。
下面我们对上述代码进行测试:
可以看出当数组为空时,其默认值并不为0,是系统随机给出的,下面给出运行结果:
int a = 10; int b[a] = { 1,2,3,4};//在定义数组时[]中的数字一定要是个常量
此处经常会有同学这样定义一个数组,我们会发现此时会报错,原因是在定义数组时[]内必须为一个常量,此时a为变量,不能放进去
此时有同学会想到一个关键字,也就是const,那么此时我们来思考,如果在int a前加上const,即如下图所示,那么此时结果如何?
const int a = 10; int b[a] = { 1,2,3,4};
此时我们会发现编译器还是会报错,与c++不同的是,在c语言中,加上const后其本质上还是一个变量,我们称之为常变量,而在c++中加上const后为一个常量,所以此时加上const后不能改变其是变量的事实.
我们都知道我们如果要遍历打印一个数组的话,一般此时可以直接在主函数中写一个数组的遍历即可,那么此时我们若想要使用函数的调用该怎么写呢,下面我们来看一段代码,并逐个分析:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> //数组名代表了首元素的地址 void get(int v[],int len) { int i = 0; for (i = 0; i <len; i++) { printf("%d\n", v[i]); } } int main(){ int b[5] = { 1, 2, 3, 4, 5 }; int len = sizeof(b) / sizeof(b[0]);//求数组的长度 get(b, len);//打印1,2,3,4,5五个数字 return 0; }
此时我们定义了一个get方法来遍历输出数组,括号中定义了两个形参,其中一个存放数组,另一个存放数组的长度,此时在主函数中定义一个数组b,并通过公式int len = sizeof(b) / sizeof(b[0])(数组的长度=数组整体的字节大小/每个数据的字节大小)求出其数组长度为5,原因是此处的b数组不仅进行了定义还进行了初始化,那么sizeof(b)求的便是数组整体的字节大小,因为数组中有五个字节大小为4的整形元素,所以大小为20,而sizeof(b[0])中所求的是整形数组第一个元素的字节大小,为4,此时20/4=5,便求出来数组的长度为5了,那么调用get方法便可以对此数组进行打印输出了。
输出结果为:
在这里大家思考一个问题,为什么不在get方法中写出求数组长度的公式呢?而要在主函数中写出?下面顺着这个思路我们来看下代码的输出结果:、
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void get1(int v[]) { int i = 0; int len = sizeof(v) / sizeof(v[0]); //此时我们将求数组长度的方法定义在 for (i = 0; i <len; i++) { printf("%d\n", v[i]); } } int main(){ int b[5] = { 1, 2, 3, 4, 5 }; get1(b); return 0; }
来看输出结果:
分析:假如在get1方法中写入求数组长度公式的话,此时len的值为1,而不是v数组本身的数组长度,原因是因为数组虽然定义了但未初始化,那么此时sizeof(v)所求的便不再是数组的字节大小,而是首元素地址的字节大小(因为数组名本来就代表首元素的地址,上述代码放在主函数中求数组长度是因为当数组不仅定义而且初始化时,此时sizeof(数组名)所求的便是数组的字节大小,并不是首元素地址的字节大小了),而我们都知道地址是十六位进制表示,也就是一个整形数字,那么sizeof(一个整型数字)最终的结果为4,而在sizeof(v[0])中所求的是整形数组第一个元素的字节大小,同样仍为4,4/4最终为1,所以求不出数组的长度。
一维数组的内存中的存储
下面我们来探讨下一维数组在内存的存储,首先我们先来看下一般的局部变量在内存中的存储:先来看一段代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main(){ int a = 10; int b = 20; int c[3] = { 1, 2, 4 }; printf("%d\n",&a); printf("%d\n",&b); printf("%d\n",&c[0]); printf("%d\n",&c[1]); printf("%d\n",&c[2]); return 0; }
此时我们来对代码进行分析:局部变量首先都存储于栈上,栈的特点为先进后出,那么此时a先进去,然后b进去,那么到底在栈上是如何存储的呢?