三年考点总结
数组类问题
分析一下代码段,并解释输出结果和原因
#include<stdio.h>
int main(int argc,char *argv[])
{
int nums[3][3] = {
1,2,3,4,5,6,7,8,9};
printf("%d\n",nums[1][-2]);
printf("%d\n",(-1)[nums][5]);
printf("%d\n",-1[nums][5]);
return 0;
}
输出结果
2,3,-9
这个题的关键是理解数据在数组中是如何存储的
。 0 1 2
0:1 2 3
1:4 5 6
3:7 8 9
第一个可以换成如此格式,*( *(nums + 1)-2)//由此可见指针和多维数组的关系不言而瑜
ps:(-1)[nums][5]) 和 nums[-1][5] 是一样的
-1[nums][5]和 -nums[1][5](这个-1没括号)
nums是二维数组,它的的单个元素是一维数组,所以它+1是+一个一维数组的字节。现在我们把这个二维数组抽象为二维指针,*(nums+1) 则是一级指针,它的单个元素为一个 int,所以它-2是 减2个int字节,所以最终就是+1个int也就是答案2。
对于这道题,还有一个问题是关于数组名具体代表的是什么的问题
int a[3][4]
- sizeof(a),a的类型: int [3][4],所以它返回整个数组的长度
- fun(int *a),作为函数形参,a的类型为int *
- &a,它的类型为int (*)[3][4],是一个数组指针
- 在表达式中,它的类型为int (const*)[4],即指向数组首元素a[0]的常量指针,a[0]它是一个int[4]。
- c语言中严格来说没有什么二维数组,它只有那种普通的一维数组,二维数组可以看做数组的数组,即对于a来说,它有3个元素,每个元素都是一个具有4个整形元素的一维数组(int[4])。我们可以把a[0]看做第一个元素的数组名,其他类推。
- 显然*a = *(a + 0) = (0 + a) = a[0] = 0[a],加法具有交换律嘛。那么,a = &a[0],这时就验证了我们上面的说法,此时(在表达式中),a是一个int()[4]
- a + 1 <==> &a[0] + 1,就是跨过第一行,即一个int[4]。a[0] + 1就是跨过第一行的第一个元素,即&a[0][1]。&a + 1自然就跨过整个数组喽。
然后我们在看一下指针和多维数组的关系
我的理解简单的说,就是一层数组等于一个 *
例如:*( *(a+x)+y) 所指向的值就是 a[x][y]
看下题
#include<stdio.h>
int main(){
int a[4][2] = {
{
2,4},{
6,8},{
1,3},{
5,7}};
printf(" a = %p, a + 1 = %p\n",a,a+1);
printf(" a[0] = %p, a[0] + 1 = %p\n",a[0],a[0]+1);
printf(" *a = %p, * a+1 = %p\n",*a,*a+1);
printf(" a[0][0] = %d\n",a[0][0]);
printf(" *a[0] = %d\n",*a[0]);
printf(" **a = %d\n",**a);
printf(" a[2][1] = %d\n",a[2][1]);
printf("*(*(a+2)+1) = %d\n",*