指针与多维数组
int coco[3][2]; //先定义一个二维数组
在这个数组中,coco是一个占有两个int类型大小的地址;coco[0]是一个占有一个int类型大小的地址
对二维数组的理解
coco==&coco[0] //两者是相等的
/*二维数组可以看出两个一维数组,一个一维数组包括了第二个一维数组
这里coco就是这个二维数组的第一个一维数组的数组名,同时coco[0]就是这个一维数组的第一个元素(一个数组元素)
把coco[0]当成二维数组的第二个一维数组的数组名,coco[0][0]就是这个一维数组的第一个元素(一个int元素)
所以此时coco这个变量名是个地址,coco[0]这个变量名也是一个地址*/
同时coco和coco[0]两者表示的内容都是这个数组的第一个元素,这也是它们为什么地址相同
数组的元素下标越界问题
在数组中,数组的元素是连续存储的,所以只要下标引用的元素没有超过存储的范围,在那个位置还有元素在,就能得到那个位置的元素;而超过了存储的范围,就只能得到未知数
例:
include<stdio.h>
#include<stdlib.h>
int main(void)
{
int Cp[2][2]={8,9,10}; //只有一个存储单元,元素连续存储
int *p1=Cp[0];
printf("%d\n%d",*p1,*(p1+2)); //输出的结果未8和10
system("pause");
return 0;
}
在多维数组中,就有些不同了。即使每个存储单元中用户没有输入数据,也会默认为0
例:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int Ar[2][2]={{1},{2,3}}; //花括号中元素欠缺的部分默认为0
int Cp[3][2]={{8},{},{5,4}}; //3个存储单元,元素不连续存储
int *p=Ar[0];
int *p1=Cp[0];
printf("%d\n%d",*p,*(p+2)); //输出的结果为1和2
printf("%d\n%d",*p1,*(p1+5)); //输出的结果为8和4
system("pause");
return 0;
}
指针与多维数组的使用
例:
#include<stdio.h>
//void fun(int p1[][3]) 与下面的定义相同,第一个[]表示p1是指针
//void fun(int p1[2][3]) 有效,但3会被忽视
void fun(int (*p1)[3]) //定义一个指向3个int的指针
{
p1[1][2]=7;
//这里不用返回,使用void类型
}
void main(void)
{
int arr[2][3]={{1,2,5},{3,4,6}};
int **p1;
p1=arr;
fun(p1);
printf("%d",arr[1][2]);
}
使用指针处理二维数组函数
//声明两个子函数来求元素“每一行”和“每一列”的总和
#include<stdio.h>
#include<stdlib.h>
#define Rows 3
#define Cols 4
void sum_rows(int ar[][Cols],int rows); //用指针对二维数组声明的三种形式
void sum_cols(int [][Cols],int);
int sum2d(int(*ar)[Cols],int rows);
int main(void)
{
int junk[Rows][Cols]={{2,4,6,8},{3,5,7,9},{12,10,8,6}}; //使用宏定义变量
sum_rows(junk,Rows);
sum_cols(junk,Rows);
printf("sum of all elements=%d\n",sum2d(junk,Rows));
system("pause");
return 0;
}
void sum_rows(int ar[][Cols],int rows)
{
int r;
int c;
int tot;
for(r=0;r<rows;r++) //使用两个for语句,循环使用每一个数组元素
{
tot=0;
for(c=0;c<Cols;c++)
tot+=ar[r][c]; //求“每一行”的总和
printf("row %d:sum=%d\n",r,tot);
}
//无返回值,使用void类型
}
void sum_cols(int ar[][Cols],int rows)
{
int r,c;
int tot;
for(c=0;c<Cols;c++)
{
tot=0;
for(r=0;r<rows;r++)
tot+=ar[r][c]; //求“每一列”的总和
printf("col %d:sum=%d\n",c,tot);
}
}
int sum2d(int ar[][Cols],int rows)
{
int r;
int c;
int tot=0;
for(r=0;r<rows;r++)
for(c=0;c<Cols;c++)
tot+=ar[r][c]; //求所有元素的总和
return tot; //返回值为int类型
}
变长数组
在创建数组的时候,使用变量指定数组的长度
例:
#include<stdio.h>
#define Rows 3
#define Cols 4
int sum2d(int rows,int cols,int ar[rows][cols]); //声明一个以变长数组为形参的函数
//因为ar的声明要使用rows和cols,所以这两个变量的声明要在ar之前
int main(void)
{
int junk[Rows][Cols]={{2,4,6,8},{3,5,7,9},{12,10,8,6}}; //创建实际数组
int morejunk[Rows-1][Cols + 2]={{20,30,40,50,60,70},{5,6,7,8,9,10}}; //创建实际数组
int i,j;
//定义一个变长数组varr
int rs=3,cs=10;
int varr[rs][cs]; //创建实际数组
for(i=0;i<rs;i++)
for(j=0;j<cs;j++)
varr[i][j]=i*j+j;
printf("3x5 array\n");
printf("sum of all elements=%d\n",sum2d(Rows,Cols,junk));
printf("2x6 array\n");
printf("sum of all elements=%d\n",sum2d(Rows-1,Cols+2,morejunk));
printf("3x10 array\n");
printf("sum of all elements=%d\n",sum2d(rs,cs,varr));
return 0;
}
int sum2d(int rows,int cols,int ar[rows][cols]) //ar是个指向数组的指针,实际并未创建数组
{
int r;
int c;
int tot=0;
for(r=0;r<rows;r++)
for(c=0;c<cols;c++)
tot+=ar[r][c];
return tot;
}
注:
1.上面两个程序展示了指针处理二维数组函数和变长数组的声明和定义的不同,同时要注意变长数组无论是在函数中声明还是在函数形参中声明,都不能使用static和extern类的存储类型说明符,而且不能再声明中初始化它们
2.变长数组名实际是个指针,带变长数组作形参的函数实际也是再原有的数组上处理数组
3.要在声明变长数组时使用const,该数组的定义必须是在块中的自动存储类别数组