C语言程序设计实践数组与指针字符串与指针链表栈队列第一章数组与指针指针与一维数组指针与多维数组返回指针值的函数1.1一维数组的定义定义方式:数据类型数组名[常量表达式];合法标识符可以是常量和符号常量,不能是变量。其值表示元素个数,数组的下标从0开始。[]:数组下标运算符单目运算符优先级:15(最高)左结合下标不能用圆括号()例inta[6];a[0]0145a[1]a[2]a[3]a[4]a[5]23aC语言在编译时给数组分配一段连续的内存空间。内存字节数=数组元素个数*sizeof(元素数据类型)数组名表示该数组所占内存区域的首地址,是地址常量。一、一维数组数组元素的类型例intn=15;intdata[n];(不能用变量定义数组元素的个数)例intdata[5];data[5]=10;//C语言对数组不作越界检查,使用时要注意!1.1一维数组的定义在一个定义语句中,可以有多个数组说明符,也可以变量与数组说明符同时出现,彼此间以逗号相隔。例inta[10],b[5],c,d;//定义了两个一维数组、两个整型变量!floatx[20],y[10],z;数组必须先定义,后使用只能逐个引用数组元素,不能一次引用整个数组。例inta[10];printf(“%d”,a);()必须for(j=0;j10;j++)printf(“%d\t”,a[j]);()1.2一维数组的引用数组元素表示形式:数组名[下标]其中:下标可以是常量,也可以是变量或表达式;若下标的值不是整型值,C语言会自动取整。下标表达式的取值要在0~常量表达式-1这个有效范围内,即不能超过数组定义时的下标上、下界范围,否则在程序执行时将造成错误。初始化方式在定义数组时,为数组元素赋初值。(在程序编译阶段使之得到初值)例如:inta[5]={1,2,3,4,5};等价于:inta[5];a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;说明:数组不初始化,其各元素的值均为随机数静态数组(static)不初始化,系统会自动给各元素赋以0值若只给部分数组元素赋初值,其它数组元素自动赋以0值当所赋初值多于定义数组的元素个数时,则编译时出错当全部数组元素赋初值时,可不指定数组长度例如:inta[5]={6,2,3};等价于:a[0]=6;a[1]=2;a[2]=3;a[3]=0;a[4]=0;例如:inta[3]={6,2,3,5,1};()例如:staticinta[5];等价于:a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;例如:inta[]={1,2,3,4,5,6};编译系统会根据初值个数自动确定数组元素的个数1.3一维数组的初始化2.1二维数组的定义定义方式:数据类型数组名[常量表达式][常量表达式];例如:inta[3][4];floatb[2][5];inta[3,4];()行数列数元素个数=行数*列数二、二维数组C语言允许使用多维数组定义a为三维整型数组,共2╳3╳4=24个元素。例如:inta[2][3][4];数组元素在内存中的存放顺序inta[3][2]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]014523a[0][0]a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]二维数组在内存中占有一串连续的存储单元,并采用“按行存放”方式,即先顺序存放第0行的各元素,再顺序存放第1行的各元素。例inta[3][4];2016172018192020212022232008920101120121320141520001200232004520067a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3](2)每个元素a[i]由包含4个元素的一维数组组成(1)二维数组a由3个数组元素a[0]、a[1]、a[2]组成a[0]a[1]a[2]行名014523a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[0][0]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]a[1][2]67101189a[0]a[1]a[2]由下标运算符的左结合性可知,多维数组的下标是按先左后右的顺序与数组名结合,然后才进行下标运算。二维数组理解存储顺序引用形式:数组名[下标][下标]说明:1.每个下标表达式的值必须是整数,且不得超越数组定义中各维的上、下界范围。2.两个下标分别放在两个方括号内。如:a[1,2],a(i,j)都是不合法的。3.若要引用二维数组的全部元素,常用二重循环来配合。例如:inta[3][4],i,j;for(i=0;i3;i++)for(j=0;j4;j++)scanf(“%d”,&a[i][j]);2.2二维数组元素的引用1.分行初始化:例inta[2][3]={{1,2,3},{4,5,6}};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123456全部初始化例inta[2][3]={{1,2},{4}};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]120400部分初始化例inta[][3]={{1},{4,5}};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]100450第一维长度省略初始化2.3二维数组元素的初始化例inta[2][3]={1,2,3,4,5,6};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123456全部初始化例inta[2][3]={1,2,4};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]124000部分初始化例inta[][3]={1,2,3,4,5};a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]123450第一维长度省略初始化2.按元素排列顺序初始化array[0]array[1]array[2]array[3]array[9]...整型指针p&array[0]p数组名是表示数组首地址的地址常量!三、一维数组和指针1.一维数组和数组元素的地址在C语言中,允许指针指向任何类型的对象,如数组、函数、结构体等。数组指针——指向数组的起始地址/首地址的指针例intarray[10];int*p;p=&array[0];//p=array;或int*p=&array[0];或int*p=array;a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素*p*(p+1)*(p+2)*(p+9)数组元素的引用——下标法和指针法*指针运算,由地址求内容[]数组下标运算符a[i]p[i]*(p+i)*(a+i)在C语言中,一维数组的任何一个元素的地址,都可以用其数组名加上一个偏移量来表示。即:&a[i]a+i*&a[i]a[i]*(a+i)a[0]a[1]a[2]a[3]a[9]...aa+9a+1a+2地址元素下标法a[0]a[1]a[2]a[9]a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9)a[i]p[i]*(p+i)*(a+i)*a*(a+1)*(a+2)*(a+9)p[0]p[1]p[2]p[9]2.通过指针引用数组元素inta[10],*p=&a[0];a=a+1;×a++;×p=p+1;√p++;√数组名作函数参数,实参与形参的对应关系实参形参数组名指针变量数组名指针变量数组名数组名指针变量指针变量3.数组名或指针作形参当数组名作为函数的参数,传递的将是数组的首地址,此时实参数组和形参数组将共用同一段内存。如果被调函数对该段内存中的数据作了修改,即数组元素的值发生变化。函数调用结束后,实参数组对应元素的值也已经改变。ij379110675420123456789ijijijji11760594723voidinv(intx[],intn){intt,i,j,m=(n-1)/2;for(i=0;i=m;i++){j=n-1-i;t=x[i];x[i]=x[j];x[j]=t;}}main(){inti,a[10]={3,7,9,11,0,6,7,5,4,2};inv(a,10);printf(Thearrayhasbeenreverted:\n);for(i=0;i10;i++)printf(%d,,a[i]);printf(\n);}m=4例:将数组a中的n个整数按相反顺序存放1.实参与形参均用数组例:将数组a中的n个整数按相反顺序存放voidinv(int*x,intn){intt,*p,*i,*j,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i++,j--){t=*i;*i=*j;*j=t;}}main(){inti,a[10]={3,7,9,11,0,6,7,5,4,2};inv(a,10);printf(Thearrayhasbeenreverted:\n);for(i=0;i10;i++)printf(%d,,a[i]);printf(\n);}2.实参用数组,形参用指针变量例:将数组a中的n个整数按相反顺序存放voidinv(int*x,intn){intt,*i,*j,*p,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i++,j--){t=*i;*i=*j;*j=t;}}main(){inti,a[10],*p=a;for(i=0;i10;i++,p++)scanf(%d,p);p=a;inv(p,10);printf(Thearrayhasbeenreverted:\n);for(p=a;pa+10;p++)printf(%d,*p);}3.实参与形参均用指针变量voidinv(intx[],intn){intt,i,j,m=(n-1)/2;for(i=0;i=m;i++){j=n-1-i;t=x[i];x[i]=x[j];x[j]=t;}}main(){inti,a[10],*p=a;for(i=0;i10;i++,p++)scanf(%d,p);p=a;inv(p,10);printf(Thearrayhasbeenreverted:\n);for(p=arr;parr+10;p++)printf(%d,*p);}4.实参用指针变量,形参用数组例:将数组a中的n个整数按相反顺序存放int*p与intq[10]数组名是指针(地址)常量p=q;p+i是q[i]的地址数组元素的表示方法:下标法和指针法,即若p=q,则p[i]q[i]*(p+i)*(q+i)形参数组实质上是指针变量,即intq[]int*q在定义指针变量(不是形参)时,不能把int*p写成intp[];系统只给p分配能保存一个指针值的内存区(一般2字节);而给q分配2*10字节的内存区一级指针变量与一维数组的关系实际上,二维数组可以理解为由多个一维数组为元素构成的数组。例如,对于二维数组inta[3][4],有(1)a是数组名,包含三个元素:a[0],a[1],a[2](2)每个元素a[i]又分别是一个包含4个元素的一维数组四、指针与二维数组对于二维数组:(1)a是数组名,包含三个元素a[0],a[1],a[2](2)每个元素a[i]又是一个包含4个元素的一维数组aa+1a+2*(*(a+0)+1)*(a[0]+1)inta[3][4];a[0]a[1]a[2]200020082016200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]