1 数组的定义
为了存放鞋子,假设你把衣柜最下面的一层分成了 10 个连续的格子。此时,让他人帮你拿
鞋子就会很方便,例如你可直接告诉他拿衣柜最下面一层第三个格子中的鞋子。同样假设现在我
们有 10 个整数存储在内存中,为方便存取,我们可以借助 C 语言提供的数组,通过一个符号来
访问多个元素。
某班学生的学习成绩、一行文字、一个矩阵等数据的特点如下:
(1)具有相同的数据类型.
(2)使用过程中需要保留原始数据.
C语言为了方便操作这些数据,提供了一种构造数据类型——数组.所谓数组,是指一组具有相同数据类型的数据的有序集合.
一维数组的定义格式为:
类型说明符数组名[常量表达式];
例如:
int a[10];
定义一个整型数组,数组名为a,它有10个元素。
声明数组时要遵循以下规则:
(1)数组名的命名规则和变量名的相同,即遵循标识符命名规则。
(2)在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度.
(3)常量表达式中可以包含常量和符号常量,但不能包含变量。也就是说,C语言不允许对数组的大小做动态定义,即数组的大小不依赖于程序运行过程中变量的值.
以下是错误的声明示例(最新的C标准支持,但是最好不要这么写):
int n;
scanf("%d", &n);/*在程序中临时输入数组的大小*/int a[nl;
数组声明的其他常见错误如下:
float a[0; /*数组大小为О没有意义*/
int b(2)(3); /*不能使用圆括号*/
3int k=3, a[kl; /*不能用变量说明数组大小*/
2.一维数组在内存中的存储
语句int mark[100};定义的一维数组 mark在内存中的存放情况如下图所示,每个元素都是
整型元素,占用4字节,数组元素的引用方式是“数组名[下标]",所以访问数组mark 中的元素的方式是 mark[0],mark[1]..,mark[99].注意,没有元素mark[100],因为数组元素是从03开始编号的.
下面介绍一维数组的初始化方法.
(1)在定义数组时对数组元素赋初值.例如,
int a[10]={
0,1,2,3,4,5,6,7,8,9l;
不能写成
inta[ a[10]={
0,1,2,3,4,5,6,7,8,9l;
(2)可以只给一部分元素赋值.例如,
int a[10]-{
0,1,2,3,4};
定义a数组有10个元素,但花括号内只提供5个初值,这表示只给前5个元素赋初值,后5个元素的值为0.
(3)如果要使一个数组中全部元素的值为0,那么可以写为
int a[10]={
0,0,0,0,0,0,0,0,0,0}或int a[10]={
0};
(4)在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组的长度.例如,
int a[]={
1,2,3,4,5};
3.数组的访问越界
下面借助一个数组的实例来掌握数组元素的赋值、访问越界.下例中给出了该例的全部代码.
【例】一维数组的存储及访问越界.
#finclude <stdlo.h
//数组越界
int main()
{
int a[5]={
1,2,3,4,5};//定义数组时,数组长度必须固定
int j=20;
int i=10;
a[5]=6;//越界访问
a[6]=7;//越界访问会造成数据异常
printf("i=%d\n"",i);//i发生改变
return 0;
}
数组另一个值得关注的地方是,编译器并不检查程序对数组下标的引用是否在数组的合法范围内.这种不加检查的行为有好处也有坏处,好处是不需要浪费时间对有些已知正确的数组下标进行检查,坏处是这样做将无法检测出无效的下标引用.一个良好的经验法则是:如果下标值是通过那些已知正确的值计算得来的,那么就无须检查;如果下标值是由用户输入的数据产生的,那么在使用它们之前就必须进行检查,以确保它们位于有效范围内.
4.数组的传递
#include <stdio.h>
//一维数组的传递,数组长度无法传递给子函数//C语言的函数调用方式是值传递
vold print(int b[],int len)
{
int i;
for(i=O;i<len;i++)
{
printf("%3d",b[i]);
}
b[4]=20;//在子函数中修改数组元素
printf( "\n");
}
//数组越界
//一维数组的传递
#define N 5
int main()
{
int a[5]={
1,2,3,4,5};//定义数组时,数组长度必须固定print(a,5);
printf("e[4]=%d\n",a[4]);//a[4]发生改变
return 0;
}
进入print函数,这时会发现数组b的大小变为8字节,==这是因为一维数组在传递时,其长度是传递不过去的,所以我们通过len来传递数组中的元素个数==.实际数组名中存储的是数组的首地址,在调用函数传递时,是将数组的首地址给了变量b (其实变量b是指针类型,具体原理会在指针节讲解),在b[的方括号中填写任何数字都是没有意义的。这时我们在print 函数内修改元素b[4]=20,可以看到数组b的起始地址和 main 函数中数组a的起始地址相同,即二者在内存中位于同一位置,当函数执行结束时,数组a中的元素a[4]就得到了修改.