知识点总结:
一:二维数组及其定义
初始化
1)分行给二维数组赋初值
2)将所有数据写在一个花括号内
3)只对部分元素赋初值,其他元素值自动置零
二维数组定义中缺省行数(列数不可省),例:
int a[][4]={1,2,3,4,5,6,7,8}; //要求对全部元素赋初值
int a[][4]={{0,0,3},{},{0,10}}; //要求分行赋初值
二: 二维数组元素的引用
输入输出二维数组元素(输入时将每行每列保存到内存空间)
输出时按不同格式输出
1)行序优先 //与输入相同
2)列序优先 //将原来的列作为行输出【1)的转秩】
矩阵的转秩(或用输出格式控制)
3)倒序输出
三:二维数组的存储
二维数组的存储:按行连续存放(行序优先);二维数组可视为(元素是一个一堆数组的)一维数组
行地址 a+i 即&a[i],区别于a[i]
列地址 a[i]+j 即 &a[i][j]
一层一层剥开我的心
四:使用指针操作二维数组
数组指针:*p / (*p)[j]指向一维数组的指针变量
区分p是指向元素的指针(列地址)or指向一维数组的指针(行地址),即指针的类型要匹配
指针数组:*a[i]定义的是数组,数组元素是指针,a[i]是指向第i行数组的指针(列地址)
//指针数组(数组元素是指针)
#include <stdio.h>
int main(){
int b[2][3]={{1,2,3},{2,4,6}};
int *pb[2];
int i,j;
/* pb是一个二级指针,pb[0]则是一级指针
b[0]是列指针,是存放着1,2,3的一维数组 */
pb[0]=b[0];
pb[1]=b[1];
for(i=0;i<2;i++){
for(j=0;j<3;j++){
printf("%2d",*pb[i]);
pb[i]++;
}
printf("\n");
}
return 0;
}
若将程序做以下改动:
#include <stdio.h>
int main(){
int b[2][3]={{1,2,3},{2,4,6}};
//int *pb[2];
int i,j;
//pb[0]=b[0];
//pb[1]=b[1];
for(i=0;i<2;i++){
for(j=0;j<3;j++){
printf("%2d",*b[i]);
b[i]++;
}
printf("\n");
}
return 0;
}
分析:主函数中的变量b是定义的数组,虽然代表了数组首地址和第一个元素的地址,
但是是不能改变的,不能对其做赋值运算。这个时候就可以定义一个指针数组
五:多维数组作函数参数
例 3个学生4门课,计算总平均分,并输出第n个学生成绩
注意函数的声明、定义和调用
声明p是指向元素的指针调用列地址;声明p是指向一维数组的指针调用行地址
//多维数组名作函数参数(数组指针的应用)
#include <stdio.h>
void average(int *p,int n); //P是指向一维数组的指针(全部元素形成的一维数组)
void search(int (*p)[4],int n); //P是指向一维数组的指针(每行元素形成的一维数组)
int main(){
int score[3][4]={{1,2,3,4},{2,3,4,5},{3,4,5,6}};
average(*score,12); //列地址,指向每一个元素
search(score,2); //行地址,指向每一行数组
return 0;
}
void average(int *p,int n){ //p是指向一个一维数组(一行12个元素)的指针
int sum=0,aver,*p_end;
p_end=p+n-1; //提前定义最后一个元素的地址值
for(;p<=p_end;p++) //用一个一级指针去遍历一个二维数组,需要把一个二维数组看成一维的
sum+=*p;
aver=sum/n;
printf("average=%4d\n",aver);
}
void search(int (*p)[4],int n){
int i;
printf("No.%d: ",n);
for(i=0;i<4;i++)
printf("%4d",*(*(p+n)+i)); //二维数组的逻辑结构并不是一维的,以一维的形式保存在内存
}