老话有句说--差之毫厘,谬以千里。
人也分两种,一种人是凡事尽善尽美型的,另一种人就是马马虎虎型的。
int main(int argc, char *argv[])
{
int a[] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d",*(a+1),*(ptr-1));
getchar();
return 0;
}
上面这段代码的输出为 2 5
关键是下面这句:
int *ptr = (int*)(&a+1);
对数组a取地址的含义是----int (*p)[5]
指向a[5]数组的指针;
虽然a=&a,但是含义是不相同的。
所以,&a+1是整个指针向前移动一个
数组的单位。
ptr |
因此,输出为2 5;
同理对于二维数组也是一样的;
int main(int argc, char *argv[])
{
int a[] = {1,2,3,4,5};
int b[2][5] = {1,2,3,4,5,6,7,8,9,10};
int *ptr = (int*)(&a+1);
int *ptrb = (int*)(&b+1);
printf("%d %d",*(a+1),*(ptr-1));
printf("\n");
printf("%d",*(ptrb-1));
getchar();
return 0;
}
b的输出为10;
与之相对应之前第一遍做这道题时候的测试代码:
/*面试宝典P78--数组名与&数组名的区别*/
#ifdef Test_P78
int main()
{
int a[] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d,%d\n",*(a+1),*(ptr-1));
getchar();
}
#endif
#ifdef Test_P78_1
int main()
{
int a[5];
int b[2][5];
printf("%d\n",&b);
printf("%d\n",b+1);
printf("%d\n",&b+1);
printf("%d\n", a);
printf("%d\n", &a);
printf("%d\n", a + 1);
printf("%d\n", &a + 1);
printf("%d\n", &a[0] + 1);
printf("---------------\n");
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(&a));
getchar();
return 0;
}
#endif
输出为:
3276360
3276380
3276400【输出为4*2*5=40+首地址3276360】
3276408
3276408
3276412
3276428
3276412
---------------
20
4
回顾整个学习的过程可以发现,从第一次做题,留下了疑问点,或者说没有及时的复习,
导致再次遇到这种题目的时候依然会解错。
当时留下的疑问点是二维数组名b取地址+1为什么是b[1]呢?
这个说法是面试宝典上面的一个错误。
然而这个错误会让人对自己的理解产生怀疑。
特别是当对&a的含义是:int(*p)[5]不够笃定的时候。
为什么不笃定,是因为对优先级int *p[5]与int (*p)[5]的理解和记忆不够娴熟;
那么该怎么办呢?
首先,这是建立在逻辑推理上的理解记忆锁链,优点是一旦打通整个
流程,那么记忆是很牢固的。缺点是如果某个环节出现了问题,会导致整个
记忆理解混乱和不确定。所以,关键是重复复习。
学习的过程中从一维到二维的问题联想是可取的,是深入思考的一种表现,是
寻求一般原理的探知精神的体现。当遇到问题时,及时的查资料,提问,方法要多样化
对于问题的讨论和沟通是解决疑问的有效手段。