4.1 一维数组的定义及引用

在讲解一维数组之前,先来看数组的定义。所谓数组,是指将那些具有相同类型的、数量有限的若干个变量通过有序的方法组织起来的一种便于使用的形式。数组属于一种构造类型,其中的变量被称为数组的元素。数组元素的类型可以是基本数据类型,也可以是特殊类型和构造类型。

先来看一维数组,它是最简单的数组类型,其定义的一般形式为:


类型说明符 数组名[常量表达式];


其中,类型说明符是数组中每个元素的类型,常量表达式是数组元素的个数。

在使用一维数组的时候需要留意以下两个要点。

常量表达式的值必须是正整数,常量表达式中不允许含有变量,而数组的命名同样要遵循标识符的命名规则。我们可以通过下面的代码来具体分析。


include<stdio.h>

void main(void)

{

int n=9;

int arr[n];

return;

}


以上代码定义了一个整型变量n=9,接下来把n作为数组定义过程中的常量表达式,编译时会出现“error C2133:'arr':unknown size”错误信息,但是使用下面的方法可以避免上述错误。


include<stdio.h>

define N 9

void main(void)

{

int arr[N];

return;

}


以上代码在预处理时将N的值替换为9,所以编译时不会出现错误。

数组元素的引用。引用数组元素的一般形式为:


数组名[下标]


在C语言中,由于数组的起始元素下标为0,所以“数组名[N]”所引用的是数组中第N+1个元素。下面通过一个简单的代码来看数组元素的引用。


include<stdio.h>

define N 9

void main(void)

{

int arr[N];

int i;

for(i=0;i<N;i++)

{

arr[i]=i+1;

printf("arr[%d]=%d\t",i,arr[i]);

if(0==(i+1)%3)

printf("\n");

}

return;

}


运行结果:


arr[0]=1 arr[1]=2 arr[2]=3

arr[3]=4 arr[4]=5 arr[5]=6

arr[6]=7 arr[7]=8 arr[8]=9


在上面的代码中,定义了一个含有9个元素的一维数组arr,在引用数组中的元素时,采用“数组名[下标]”的方式,将其中的每个元素视为一个普通的变量来进行操作。需要注意的是,因为定义的数组arr仅含有9个元素,所以在使用的过程中,下标值不能超过8,否则就会出现下标越界的错误,示例如下:


include<stdio.h>

define N 9

void main(void)

{

int arr[N];

arr[9]=9;

return;

}


以上代码在编译时不会提示任何错误信息,因为编译器并不会做数组元素下标是否越界的检测,所以在运行的时候就会出现错误。

讲解完一维数组的注意要点,接下来通过一段代码来了解一维数组在内存中是如何存放的。


include<stdio.h>

define N 4

void main(void)

{

int arr[N];

int i;

for(i=0;i<N;i++)

{

arr[i]=i;

printf("&arr[%d]=%d\n",i,&arr[i]);

}

return;

}


运行结果:


&arr[0]=1245040

&arr[1]=1245044

&arr[2]=1245048

&arr[3]=1245052


在以上代码中定义了含有4个整型元素的一维数组,每个元素占用4字节,下标从0开始,到3结束。arr数组元素在内存中的存储结构如图4-1所示。

4.1 一维数组的定义及引用 - 图1

图 4-1 arr数组元素的内存结构

从图4-1中可以看出,数组元素从第一个存储地址到最后一个存储地址呈依次递增的趋势,每个数组元素所占用的内存大小为元素类型所占用的内存大小,这里,元素类型为整型,占用4字节。当然,数组类型也可以是自定义的数据类型,示例如下:


include<stdio.h>

define N 4

struct_stu

{

char name[20];

int score;

}stu[N];

void main(void)

{

int i;

printf("自定义结构类型_stu占用的内存大小为:%d\n",sizeof(_stu));

for(i=0;i<N;i++)

{

printf("&stu[%d]=%d\n",i,&stu[i]);

}

return;

}


运行结果:


自定义结构类型_stu占用的内存大小为:24

&stu[0]=4375128

&stu[1]=4375152

&stu[2]=4375176

&stu[3]=4375200


这里的自定义数据类型在内存中的存储结构如图4-2所示。

4.1 一维数组的定义及引用 - 图2

图 4-2 stu数组元素的内存结构

从图4-2中看到,自定义的类型所占用的内存大小为24字节,所以数组stu中每个数组元素占用内存的大小为24字节,存储方式同样从低地址到高地址,并且所有数组元素都存储在一个连续的内存单元中,数组所占用的内存大小为数组元素类型所占用的内存大小乘以数组元素的个数。

对于一维数组还需要注意的就是它的初始化问题,接下来看看一维数组初始化的注意事项。一维数组初始化的一般形式为:


数组类型 数组名[N]={数组元素1,数组元素2,……数组元素N};


下面通过代码来看一维数组的初始化。


include<stdio.h>

define N 4

void main(void)

{

int i;

int arr[N]={1,2,3,4};

for(i=0;i<N;i++)

{

printf("arr[%d]=%d\n",i,arr[i]);

}

return;

}


运行结果:


arr[0]=1

arr[1]=2

arr[2]=3

arr[3]=4


从上面的运行结果可以看出,这里在定义数组时对数组元素进行的初始化,和前面采用循环的方式单独对数组中每个元素进行初始化的方法一样,但是,切不可在定义数组后再对整个数组进行赋值操作,例如:


include<stdio.h>

define N 4

void main(void)

{

int i;

int arr[N];

arr[N]={12,34};

return;

}


或者


include<stdio.h>

define N 4

void main(void)

{

int i;

int arr[N];

arr={12,34};

return;

}


这两种方式都是错误的,C语言不允许在定义了数组之后再采用以上方式对整个数组赋值,定义了数组之后,只能对数组元素中的单个元素进行赋值操作。

在对数组元素进行整体赋值的时候,如果初始化的元素的个数小于数组的长度,那么结果会怎么样呢?看看下面的代码:


include<stdio.h>

define N 4

void main(void)

{

int i;

int arr[N]={1,2};

for(i=0;i<N;i++)

{

printf("arr[%d]=%d\n",i,arr[i]);

}

return;

}


运行结果:


arr[0]=1

arr[1]=2

arr[2]=0

arr[3]=0


从上面对数组的初始化方式和运行结果发现,如果初始化的数组元素个数小于数组长度,那么编译时会将那些没有初始化的数组元素赋值为0。如果初始化元素的个数大于数组长度,又会怎么样呢?看看下面的代码:


include<stdio.h>

define N 4

void main(void)

{

int i;

int arr[N]={1,2,3,4,5,6};

for(i=0;i<N;i++)

{

printf("arr[%d]=%d\n",i,arr[i]);

}

return;

}


这段代码在编译时会提示“error C2078:too many initializers”错误,提示初始化元素过多。

在用这种方法进行初始化时也可以省略数组长度,此时数组长度由初始化的数组元素个数来决定,例如:


include<stdio.h>

void main(void)

{

int i;

int arr[]={1,2,3,4,5,6};

for(i=0;i<6;i++)

{

printf("arr[%d]=%d\t",i,arr[i]);

if(0==(i+1)%3)

printf("\n");

}

return;

}


运行结果:


arr[0]=1 arr[1]=2 arr[2]=3

arr[3]=4 arr[4]=5 arr[5]=6


在上面的代码中,在定义数组arr的时候省略了数组长度,编译器会根据初始化的数组元素个数来决定所采用的数组的长度。