int a[5];
// a 是数组名,5是数组元素的个数,从a[0]-a[4];
int b[3][4];
//3行4列,a[0][0]是第一个元素,a[i][j]是第i+1行,第j+1列的数
int c[5]={1};//其余元素都是0;
int d[8];//全是垃圾值
//所以只定义不初始化全是垃圾值,部分初始化,没被初始化的补0
一维数组名是一个指针常量,它存放的是一维数组第一个元素的地址
int a[3];
int b=5;
a=b;// error a是一个指针常量,不可以被改变
int main(void)
{
int a[3]={1,2,3};
printf("%#X\n",a); // #X以十六进制整型格式输出
printf("%#X\n",&a[0]);
return 0;
}
//输出
0X61FE14
0X61FE14
两个值完全一样,说明一维数组名存放的就是一维数组第一个元素的地址
【如果一个函数要处理一个一维数组,则需接收该数组的哪些信息?】
int f(int * pArr)
{
*pArr= 0;
/*
1. pArr代表的是数组名,也是数组第一个元素的地址
2. *pArr 代表的就是数组的第一个元素: a[0]
3. *(pArr+1)代表的就是数组的第二个元素a[1];
4. 总结: a[i] = *(Parr+i)
*/
*(pArr+1) = 100;
}
int main (void)
{
int a[3]={1,2,3};
printf ("a[0]=%d,a[1]=%d\n",a[0],a[1]);
f(a);
printf ("a[0]=%d,a[1]=%d\n",a[0],a[1]);
return 0 ;
}
为什么需要“数组名+数组长度”2个元素来确定一个一维数组?
| . | . | a[0] | a[1] | . | . | . | 未知长度 | . |
|---|
//通过 数组名,长度 输出任意一个一维数组的全部元素
# include <stdio.h>
void f(int * pArr,int len)
{
int i;
for (i=0;i<len;++i)
{
printf("%d\n",*(pArr+i));
}
return;
}
int main (void)
{
int a[3]={1,2,3};
int * P;
P=&a;
*(a+1)=200;
P[2]=100;
f(a,3);
return 0 ;
}
//输出
1
200
100
说明:a[i] = * (a+i) = * (P+i) = P[i]
实质上,数组名[下标]要以指针/地址的角度去理解,不要停留在表面
一、显然这种没有实际意义
int main (void)
{
int a=3;
int b= 5;
int *p = &a;
int *q = &b;
int x=p-q;
return 0;
}
二、指向连续存储空间的不同存储单元时
int main (void)
{
int a[5]={1,2,3,4,5};
int *p = &a[1];
int *q = &a[4];
printf("p、q所指向的空间单元相隔的个数是: %d\n",q-p);
return 0;
}
//输出:
p、q所指向的空间单元相隔的个数是: 3
假设P指向char类型的变量 假设q指向 int 类型的变量 假设r指向 double 类型的变量
p、q、r 本身所占字节数是否一样?
sizeof(数据类型)
sizeof(变量名)
int main (void)
{
int a = 4;
int *p = &a;
double b = 88.8;
double *q = &b;
float c = 4.19f;
float *r = &c;
char d = 'A';
char * m = &d;
printf("int *;double*;float*;char*分别所占的字节是:%d;%d;%d;%d",sizeof(p),sizeof(q),sizeof(r),sizeof(m));
return 0;
}
//输出:
int *;double*;float*;char*分别所占的字节是:8;8;8;8
可见,所有类型的指针变量所占的字节数是相同的。
注意: VC++ 6.0 是4个字节
和不同的编译器以及系统有关。
为什么不管什么类型的指针变量所占字节数都是相同的?
前面已经分析过,没有真正的多维数组,所谓多维数组也不过是多个一维数组
以下提到的数组皆以下例为准
int a [3][4]
该数组是含有3个元素的一维数组
只不过每个元素都相当于一个包含4个元素的一维数组。
| 图 | 例 | 子 | 数 | 组 |
|---|---|---|---|---|
| a[0] | 1 | 3 | 5 | 7 |
| a[1] | 9 | 11 | 13 | 15 |
| a[2] | 17 | 19 | 21 | 23 |
a[0]、a[1]、a[2] 分别是3个一维数组的数组名
a[0]这个一维数组,有4个元素,a[1]这个一维数组也有4个元素。
(一) 地址角度
a[0]、a[1]、a[2] 分别是3个一维数组的数组名,a、a+1、a+2代表3个一维数组起始地址, a、a+1、a+2 就分别指向a[0]、a[1]、a[2]这3个一维数组。
一维数组名是一维数组第一个元素的地址。假设a[0]数组的第一个元素的地址是2000H也就是,那么a[1]、a[2]数组第一个元素的地址是多少?
如图-例子数组 a[1] 是第二个一维数组第一个元素的首地址,值为 2016H
在一个一维数组中,数组名是第一个元素的地址,加 1就是第二个元素的地址,所以 a[0]+1 就表示第一行第二列元素的地址。
数组某元素的地址还可以用 &元素 的方式表示。 例如第1行第2列的元素的地址是? &a[0][1]
已知在一维数组中,a[i]=*(a+i) , 又根据第3条, 所以在二维数组中, a[i][m] = *(a+i)+m, 所以二维数组第一行第二列的元素地址是: * (a)+1
综上:&a[m][n]=a[m]+n=*(a+m)+n 都表示的是第M行第N列元素的地址。
a---这个a可以是定义的二维数组的数组名,也可以是第一行的一维数组的数组名,也可以是第一行一维数组元素的首地址。
(二) 元素角度
int main (void)
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for(p=a[0];p<a[0]+12;p++) //使 p 依次指向下一个元素
{
if ((p-a[0])%4==0) //P 移动4次后换行
{
printf("\n");
}
printf("%4d",*p);
}
printf("\n");
return 0;
}
//输出一个二维数组指定某一行某一列的值
int main (void)
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4],i,j;//指针变量P指向包含4个整形元素的一维数组
p=a; //P指向二维数组的第0 (1) 行
printf("Please enter row and colum:");
scanf("%d,%d",&i,&j);//输入要输出的是某行某列
printf("a[%d,%d]=%d\n",i,j,*(*(p+i)+j));
return 0;
}
# include <stdio.h>
/*
1. 求3个学生,每个学生有4门课的总成绩的平均值
2. 计算第n个学生的成绩
*/
void average(double *p,int n) //n是数组元素个数
{
//这个函数实际上把二维数组当作一维数组来处理的
double *p_end; //创建一个指针变量指向二维数组的最后一个元素
double sum = 0,aver;
p_end = p+n-1; // 结尾指针指向数组的最后一个元素
for (;p<p_end;p++)
{
sum = sum + *p; //通过指针依次指向二维数组的每一个元素算累加和
}
aver = sum/n;
printf("average=%5.2lf\n",aver);
}
void search(double (*p)[4],int n) //p是指向具有4个元素的一维数组的指针
{
int i;
printf("The score of No.%d are:\n",n);
for(i=0;i<4;i++) // i用来循环第n个学生的每一科成绩
{
printf("%.2lf ",*(*(p+n)+i)); //输出第n行第i列元素
}
printf("\n");
}
int main(void)
{
double score[3][4]={{66,67,89,99},{65,78,98,66},{79,69,95,100}};
average(*score,12);// *score符合函数参数输入地址(指针)的要求,*score 是数组第一个元素的地址
search(score,2);
return 0;
}
/*输出
average=72.58
The score of No.2 are:
79.00 69.00 95.00 100.00
*/
本文章使用limfx的vsocde插件快速发布