C语言第15天,指针与多维数组

## 数组名的转换规则

当数组名arr出现在一个表达式当中,数组名arr将会被转换为指向数组首元素的指针。

但是,这个规则有两个例外:

1.对数组名arr使用sizeof时。

2.对数组名arr使用&时。

 

多维数组和指针

1.首先, 我们来探究数组名。

#include<stdio.h>

int main()

{

int A[10];

int B[5][10];

printf("sizeof A=%d\n",sizeof(A));

printf("sizeof B=%d\n",sizeof(B));

return 0; }

结果为sizeof A=40

sizeof B=200

A、B的类型为都为整形数组,sizeof B=(4*10)*5=200

2.数组指针与指针数组

#include<stdio.h>

int main()

{int A[10];

int B[5][10];

类型1 pA;

类型2 pB;

pA=A;

pB=B;

return 0;}

数组名A、数组名B将会被转换为指向数组首元素的指针,之后赋值给pA或pB。

除了void*,不同指针类型之间不能直接相互赋值。因此,在表达式pA=A以及pB=B中,赋值运算符两边的指针类型必须一致。

int*pA;

int(*pB)[10];//int*pB[10]会被误认为有10个元素并且元素类型为int*的数组,即一个指针数组了。如果星号*和变量名被括号()包括,那么这是一个指针的声明。

 

3.数组指针的移动

#include<stdio.h>

int main()

{int B[5][10]={

{0,1,2,3,4,5,6,7,8,9},

{10,11,12,13,14,15,16,17,18,19},

{20,21,22,23,24,25,26,27,28,29},

{30,31,32,33,34,35,36,37,38,39},

{40,41,42,43,44,45,46,47,48,49}

};

 

int(*pInt10)[10]=B;//int[5][10]转换为int(*)[10]

 

printf("pInt10=%d\n",pInt10);//指向B[0][10]

printf("pInt10+1=%d\n",pInt10+1);//指向B[1][10]

printf("pInt10+2=%d\n",pInt10+2);//指向B[2][10]

printf("pInt10+3=%d\n",pInt10+3);//指向B[3][10]

printf("pInt10+4=%d\n",pInt10+4);//指向B[4][10]

return 0;}

 

数组名B的类型为int[5][10],但是它出现在初始化表达式中。所以,会被转换为指向首元素的指针,即int(*)[10]。

指针pInt10指向类型为int[10]的数组,所以指针pB移动的步长应当为sizeof(int[10]),即40。

 

 

4.对数组指针取值

类似于int*类型,对int*取值之后,可以获得int。

pB的类型为int(*)[10],对int(*)[10]取值之后,可以获得int[10]。即*plnt10,类型为int[10],是一个数组,空间大小为40。

既然*pInt10是一个数组,若出现在表达式中,又会从int[10]转换为首元素指针,即int*类型。

#include<stdio.h>

int main()

{int B[5][10]={{0,1,2,3,4,5,6,7,8,9},

{10,11,12,13,14,15,16,17,18,19},

{20,21,22,23,24,25,26,27,28,29},

{30,31,32,33,34,35,36,37,38,39},

{40,41,42,43,44,45,46,47,48,49}

};

 

int(*pInt10)[10]=B; //int[5][10]转为int(*)[10]

 

printf("pInt10=%d\n",pInt10);

printf("pInt10+1=%d\n",pInt10+1);

 

int*pInt=*pInt10; //*pInt10从int[10]转换为int*

 

printf("pInt=%d\n", pInt);//指向B[0][0]

printf("pInt+1=%d\n", pInt+1);//指向B[0][1]

printf("pInt+2=%d\n", pInt+2);//指向B[0][2]

printf("pInt+3=%d\n", pInt+3);//指向B[0][3]

printf("pInt+4=%d\n", pInt+4);//指向B[0][4]

printf("pInt+5=%d\n", pInt+5);//指向B[0][5]

printf("pInt+6=%d\n", pInt+6);//指向B[0][6]

printf("pInt+7=%d\n", pInt+7);//指向B[0][7]

printf("pInt+8=%d\n", pInt+8);//指向B[0][8]

printf("pInt+9=%d\n", pInt+9);//指向B[0][9]

printf("pInt+10=%d\n", pInt+10);//指向B[1][0]

return 0;}

 

5.指针访问与下标访问等价

访问数组元素的两种办法:

1.数组名[下标]  2.*(数组名+偏移量)

但学完数组名出现在表达式中会转变为指针后可以得到一个更为通用的形式

1.指针[下标]

2.*(指针+偏移量)

#include<stdio.h>

int main()

{int B[5][10]={

{0,1,2,3,4,5,6,7,8,9},

{10,11,12,13,14,15,16,17,18,19},

{20,21,22,23,24,25,26,27,28,29},

{30,31,32,33,34,35,36,37,38,39},

{40,41,42,43,44,45,46,47,48,49}

};

 

int(*pInt10)[10]=B;//int[5][10]转为int(*)[10]

int*pInt=*pInt10;//*pInt10从int[10]转换为int*

 

printf("pInt[0]=%d\n",pInt[0]);//等价于*(pInt+0)

printf("pInt[1]=%d\n",pInt[1]);//等价于*(pInt+1)

printf("pInt[2]=%d\n",pInt[2]);//等价于*(pInt+2)

printf("pInt[3]=%d\n",pInt[3]);//等价于*(pInt+3)

printf("pInt[4]=%d\n",pInt[4]);//等价于*(pInt+4)

printf("pInt[5]=%d\n",pInt[5]);//等价于*(pInt+5)

printf("pInt[6]=%d\n",pInt[6]);//等价于*(pInt+6)

printf("pInt[7]=%d\n",pInt[7]);//等价于*(pInt+7)

printf("pInt[8]=%d\n",pInt[8]);//等价于*(pInt+8)

printf("pInt[9]=%d\n",pInt[9]);//等价于*(pInt+9)

printf("pInt[10]=%d\n",pInt[10]);//等价于*(pInt+10)

return 0;}

 

6.三维数组中的指针

#include<stdio.h>

int main()

{int S[2][5][10]={

{

{0,1,2,3,4,5,6,7,8,9},

{10,11,12,13,14,15,16,17,18,19},

{20,21,22,23,24,25,26,27,28,29},

{30,31,32,33,34,35,36,37,38,39},

{40,41,42,43,44,45,46,47,48,49}

},

{

{0,1,2,3,4,5,6,7,8,9},

{10,11,12,13,14,15,16,17,18,19},

{20,21,22,23,24,25,26,27,28,29},

{30,31,32,33,34,35,36,37,38,39},

{40,41,42,43,44,45,46,47,48,49}

}

};

printf("S[1][2][3]=%d",*(*(*(S+1)+2)+3));

return 0;}

 

那么S=[1][2][3]最后等于什么呢?

跟据运算优先级来分开看,S+1=int(*)[5][10]//为一个指针,指向S[2][5][10]

*(S+1)=int[2][5][10]//[2]省略,成为一个数组

*(S+1)+2=int(*)[10]//数组出现在表达式变为指针,移动两个步长,指向S[2][2][10]

*(*(S+1)+2)+3=int(*)[3]//指针先被*变为数组int[10],然后出现在表达式变为指针移动3个步长,最后成为指向S[2][2][3]的指针

最后在用*将指针变为int整型,所以结果为int的整型元素

 

posted @ 2022-09-22 19:55  纯爱暴打ntr  阅读(110)  评论(0)    收藏  举报