您的位置:首页 > 编程语言 > C语言/C++

学习笔记---数组初步

2016-12-26 19:14 225 查看
数组
意义:定义一段连续的内存空间用于保存一组同类型的数据。

格式:

定义:类型标识符  数组名 [常量表达式];

注1:同一个数组的每一个元素都必须属于同一数据类型。

注2:一个数组在内存中占用一片连续的存储单元。

注3:常量表达式最好是确定的值,因为定义数组的原理是在内存空间注册一段连续的存储单元,而如果常量表达式是定值的话,可以方便系统对内存的调度管理(一般系统为变量分配存储空间时使用内存中哪的一部分都是随机的,所以内存空间往往十分碎片化,当需求的数组很大时,要在其中找到一段连续的存储单元分配给该数组相对会更耗时。极端的来看,在程序运行的过程中才给数组定义大小(分配空间)甚至可能引起卡顿)

注4:当定义数组时,中括号内的常量表达式换成变量时,数组的大小将变成动态的。但这种定义方法是C99中新增的,在C89中不被允许。所以,一般不允许用变量作为数组的大小。

引用:数组名 [下标]

注1:数组必须先定义,后使用。

注2:不能用数组名引用数组中全部元素。

注3:下标可以使整型常量,也可以是整型变量/表达式。

数组定义的时候,可以直接初始化

例如:

int a[10]{0,1,2,3,4,5,6,7,8,9}

也可以部分初始化

例如:

int a[10]{0,1,2,3,4,5}//剩下的未被初始化的元素将自动被赋值为0

可以通过初始化数组来免去数组长度的定义

例如:

int a[ ]={1,2,3,4,5}
//等价于
int a[5]={1,2,3,4,5}

将数组定义为静态局部数组或全局数组,系统将自动给数组初始化为0

例如:

static int a[10];//这种情况下,数组中的每一个元素都将被自动初始化为0


定义其他类型的数组和定义整型数组的规律相近

例如:

char c[10]={'i',' ','a'};


代码示例1:

#include <stdio.h>
#include <stdlib.h>
/*
这个程序用于通过输入的年月日计算当前是一年的第几天
同时作为数组使用的示例
*/

int days(int y,int m,int d);

int main()
{
int year,month,day;
printf("输入年月日:");
scanf("%d %d %d",&year,&month,&day);
printf("这是该年的第%d天\n",days(year,month,day));
return 0;
}

int days(int y,int m,int d)
{
int i,sum=d;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
for(i=1;i<m;i++)
sum+=a[i];
if(m>2&&((y%4==0&&y%100!=0)||y%400==0))//假如是闰年
sum++;
return sum;
}
结果:



解析:通过将每个月的天数存储在数组中,在需要的时候再调用,来简化程序。

代码示例2:

#include <stdio.h>
#include <stdlib.h>
/*
这个程序利用数组来求解并保存Fibonacci数列的前N项
*/

int main()
{
int i,N;
printf("输入N:");
scanf("%d",&N);
int f[45]={1,1};//事实上,45个数之后的数已经过大了。int型数据无法表示。
for(i=2;i<N;i++)
f[i]=f[i-1]+f[i-2];
for(i=0;i<N;i++)
{
if((i+1)%5==0)
printf("\n");
printf("%8d\t",f[i]);
}
return 0;
}

结果:



解析:通过数组存储数列的值,当因为使用的是int型数据类型,所以能存储的数据大小有限。(当学习至自定义数据类型时,应当可以解决?)

代码示例3:

#include <stdio.h>
#include <stdlib.h>
/*
程序用于十进制数向其他进制的转换(暂时无法转换10以上的进制)。。。转换的原理在于用十进制数对目标进制数循环取模并除目标进制数。
*/
int changeNum(int R[],int N,int s);//转换的核心代码

int main()
{
printf("该程序用于十进制向N进制的转换,输入-1结束程序\n");
while(1)
{
int R[100],s,N,i;//利用的数组作为函数参数时地址传递的原理,这里提前使用,无需在意。
printf("输入希望转换的十进制数:\t");
scanf("%d",&s);
if(s==-1)
break;
printf("输入希望转换成的进制:\t");
scanf("%d",&N);
int n=changeNum(R,N,s);
printf("\n该十进制数转换为%d进制数之后为:\t",N);
for(i=n-1;i>=0;i--)
printf("%d",R[i]);
printf("\n");
}
printf("程序结束");
return 0;
}

int changeNum(int R[],int N,int s)
{
int i=0;
while(s)
{
R[i]=s%N;
s/=N;
i++;
}
return i;
}
结果:



解析:

这个程序用到了数组作为函数参数的地址传递。在指针进阶部分将解析;

拓展:

数组越界

原理:数组只可使用“授权”的空间

示例:

int a[10];

则a[0]到a[9]即是已授权的可随意使用的数组。

而如果我们试图使用a[10]以至于a[15]之类超过数组大小的空间。

就会引起一些不可预知的错误,这种错误叫做“数组越界”

解析:

数组在内存中存储形式为一段连续的内存空间。我们用数组下标访问数组元素的时候,会通过下标的值自动匹配这段内存空间中的某一段(比如a[8]代表0x280014开头的一段空间,那么a[9]代表的就是0x280018开头的空间,他们之间相隔的正好是一个int型变量的字节大小(因为a数组定义时使用的是Int类型))

当使用超过数组大小的下标来访问内存时,程序会忠实的执行命令。但a[10]代表的0x28001c并不是定义时指明要作为数组空间使用的内存单元。

所以这个内存单元可能已经被此程序的另一个变量甚至其他程序的变量使用。当对这个变量进行操作时,可能会引起BUG。甚至导致系统崩溃。

注:数组越界其实就是“野指针”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 数组 基础