我们先看一个例子
1、源程序
#include "stdio.h"
//在这里用define定义M为100
int a[M][M]={0};
void fun(int a[M][M],int m)
{
int j,k;
for(j=0;j<m;j++)
for(k=0;k<m;k++)
a[j][k]=(k+1)*(j+1);
}
int main()
{
int i,j,n;
printf("Input n:\n");
scanf("%d",&n);
fun(a,n);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%4d",a[i][j]);
printf("\n");
}//for
}
2、程序简单,只是需要有几个地方需引起我们注意。
1)数组的初始化
a)静态与全局数组:不初始化则初值自动为0
b)其它类型数组:不初始化则初值不确定
一唯数组元素的显式初始化
(1)标准形式
如:int a[4]={ 1, 2, 3, 4 };
(2) 可不指定元素个数
如:int a[]={ 1, 2, 3, 4 };
(3) 可只初始化前面部分元素
(余下部分元素初值为0)
如:int a[5]={ 1, 2, 3}; //则a[3]=a[4]=0
二唯数组元素的显示初始化
(1)标准形式
如:int a[2][3]={{1, 2,3}, {4, 5, 6} };
(2) 可缺省行数
int a[][3]={{1, 2, 3}, {4, 5, 6} };
(3) 可缺省内层{ }
int a[2][3]={1, 2, 3, 4, 5, 6 };
int a[][3]={1, 2, 3, 4, 5, 6 };
(4) 使用内层{ }时,每行可只初始化前面部分元素
(该行余下的元素初始值自动为0)
int a[][3]={{1, 2}, {4} };
(5) 指定行数时,可用内层{ }只对前面几行初始化
(余下各行的元素初始值自动为0)
int a[4][3]={{1, 2}, {4, 5, 6}, {7}};
2)函数参数传递
a)形参定义
[返回值类型名] 函数名([形参定义])
{ [定义局部变量]
[语句部分]
}
其中,形参定义详细格式为:
类型名 形参变量名{,类型名 形参变量名}
b)非数组形参
( b1)传值(非地址值)
int isprime(int m)
(b2)传地址(指针变量作形参)
void swap(double *p,double *q)
(b3)传引用(C++)
void swap(double &x,double &y)
c)数组作形参
(1) 数组作为形参时,可采用数组形式或者指针形式来说明形参的数据类型;
(2) 数组形参或者为访问数组而定义的指针形参对应的实参一般是数组的首地址表达式,即数组名;
(3) 数组只能传地址,数组元素不能整体拷贝传递;
(4) C++中,数组传递不能采用引用类型
C1) 比如一唯数组中
主函数中:
int a[N],m;
m=cnp(a);
被调函数中:
cnp(int a[]) /*下标法 */
cnp(int *a) /* 指针法 */
C2)m(m>=2)维数组作形参
有三种等价的语法格式:
(1) T1 f(T a[n1][n2]…[nm]);
/* m维数组名常量形参 */
(2) T1 f(T a[][n2]…[nm]);
/ *第一维数目可以缺省*/
(3) T1 f(T (*a)[n2]…[nm]);
/*数组对象指针变量形参(详见指针深入)*/
比如
主函数: int a[N][N];
rs(a);
被调函数中
void rs(int a[N][N]) /* 或 int a[][N] 或 int (*a)[N] */
3)变量的生存期与变量的初始化
4)指针数组和数组指针
A) 指针数组就是以指针为数组元素的数组:
int a[4]={1,2,3,4};
int *p[4]={a,a+1,a+2,a+3},
B)字符指针(字符串)数组与排序:
引例:用多个字符串初始化字符指针数组.
char *s[]={"ABCDE",
"xyz",
"STOP!",
"We study English."
};
上面的数组也常称为字符串数组。
字符串排序实质上是索引排序,即串存储位置不变,交换的是字符指针数组中的指针(索引)。
C) 数组指针
所谓数组指针,就是以一个数组作为对象的指针,或者指向数组的指针或者对象类型为数组类型的指针。
定义数组指针
语法格式:T (*id)[n1][n2]…[nm]
语法说明:id为标识符,表示数组指针变量名
功能说明:定义指针变量id, id的对象类型为:
T [n1][n2]…[nm]
即id指向的对象是一个m维n1×n2×···×nm元数组。
事实上,C语言将m维数组T a[n1][n2]…[nm]视为一个由n1个相同大小的m-1维数组([n2]…[nm])组成的一维数组。
如:int(*p) [3].
应用举例:指针类型强制(地址值不变,对象类型变)
int a[9],(*p)[3], i;
p=(int (*)[3])a; /* int * 强制为 int (*) [3] */
/* 使得9元一 维数组当做3行3列二维数组使用 */
例:inta[3][4][5], (*p)[4][5]=a+1;
若有定义T a[3][4],(*p)[4]=a;设i=0,1,2; j=0,1,2,3 则
a+i<->p+i: 指向第i行一维数组的数组指针
a[i]<->p[i]<->*(a+i)<->*(p+i) : 第i行第0个元素的地址
即第i行一维数组名
a[i]+j<->*(a+i)+j<->p[i]+j<->*(p+i)+j :
第i行第j个元素的地址
a[i][j]<->*(a[i]+j)<->*(*(a+i)+j)
<->p[i][j]<->*(p[i]+j)<->*(*(p+i)+j): 第i行j列元素
5)函数指针
A)定义函数指针变量
语法格式: T (*id)(); /* only C */
或 T (* id)(形参类型列表); /* both of Cand C++ */
例如,int (*p)();
/* 变量p指向一个返回值类型为int型的函数 */
float *(*q)(int,double); C语言可简写为float *(*q)();
函数指针类型名:
T (*)(); /* only C */
或 T (*)(形参类型列表); /* both of Cand C++ */
B) 函数指针变量的初始化与赋值操作
函数名为函数指针常量,可用于向函数指针变量提供初值或者赋值。
例如:#include "math.h"
double (*f)(double)=exp; or
f=log10;
C) 用函数指针变量调用函数
格式:函数指针变量名(实参表);
或 (*函数指针变量名)(实参数);
一个例子是:
double (*f1)(double)=sin,(*f2)(double)=cos,(*f3)(double);
f3=sqrt;
b=(*f2)(PI/3);
c=f3(2);
D) 函数指针作形参
Status LocateElem(LinkList P,ElemType e,Position &q,int(*cmp)(ElemType,ElemType))
......................则调用此函数时:
LocateElem(P,e,q,compare) //compare是实参
(完)