版本声明:本文转载于公众号TeachPlus
C语言面试题---指针篇(四)
数组,从来都是考察指针最好的载体,所以数组与指针结合的考题是最多的,下面的题目就是通
过指针和数组结合来考察指针的:
-
# include <stdio.h>
-
-
int main( void)
-
{
-
int a[
5]={
1,
2,
3,
4,
5};
-
int *ptr=(
int *)(&a+
1);
-
printf(
"%d,%d",*(a+
1),*(ptr
-1));
-
return
0;
-
}
输出结果是什么呢?
本题解析
答案:输出结果为2,5
*(a+1) 就是 a[1] , *(ptr-1) 就是 a[4] ,执行结果就是2,5
&a+1 不不是首地址+1,系统会认为加一个a数组的偏移,
是偏移了一个数组的大小(本例是5个int)
int *ptr=(int *)(&a+1) ;则ptr实际是 &(a[5]) ,也就是 a+5
原因如下:
&a 是数组指针,其类型为 int (*)[5] ;
而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。
a是长度为5的int数组指针,所以要加 5*sizeof(int) ,所以ptr实际是 a[5] 。
但是 prt 与 (&a+1) 类型是不一样的(这点很重要),所以 prt-1 只会减去 sizeof(int*)
a,&a 的地址是一样的,但意思不一样,a 是数组首地址,也就是 a[0] 的地址,
&a 是对象(数组)首地址,a+1 是数组下一元素的地址,即 a[1] , &a+1 是下一个对象的地址,即 a[5]。
相关知识点
接下来看这样的一道题目,会对于上面的题目的理解更加深刻一点:
数组int c[3][3];为什么c,*c的值相等,(c+1),(*c+1)的值不等c,*c,**c,代表什么意思?
解析:
首先看最后一个问题, c 是第一个元素的地址, *c 是第一行元素的首地址,其实第一行元素的
地址就是第一个元素的地址, **c 是提取第一个元素。
为什么 c , *c 的值相等?
c是数组名,是一个二维指针,它的值就是数组的首地址,也即第一行元素的首地址(等于 *c ),
也等于第一行第一个元素的地址( &c[0][0] );可以说成是二维数组的行指针。
*c 是第一行元素的首地址;是一个一维指针,可以说成是二维数组的列指针。
**c :二维数组中的第一个元素的值;即:c[0][0]
所以:c 和 *c的值是相等的,但他们两者不能相互赋值,(类型不同)
综上所述, (c+1) 与 (*c+1) 中:
(c+1) ,c是数组名也就是二维数组的行指针,所有 c+1 是移动一行,
将指针指向二维数组中第二行的首地址,也就是 &c[1][0] .
而 (*c+1) 中, *c 是二维数组第一行的首地址,也就是二维数组的列指针,所以 (*c+1) ,
移动的是一列,是将指针指向二维数组第一列的第二个元素,也就是 &c[0][1]
在这里,还需要提醒的一点就是所谓的数组指针和指针数组:
-
char (* str)[
20];
/*str是一个数组指针,即指向数组的指针.*/
-
char * str[
20];
/*str是一个指针数组,其元素为指针型数据.*/
再看一道题目巩固一下:
-
#
# include <stdio.h>
-
int main()
-
{
-
int arr[] = {
1,
2,
3,
4,
5,
6,
7,
8};
-
int *p=arr;
-
*(p++)+=
123;
-
printf(
"%d,%d\n", *p,*(++p));
-
return
0;
-
}
在本题中:
第一行,定义数组 arr ,元素共八个
第二行,定义指针 p 指向 arr 数组,此时的 *p 还是等于 arr 数组的第0个元素,也就是1。
第三行, p++ 里的++是最后才运算,所以先执行 *p+=123 ,也就是arr的第0个元素被赋值为123。
此时arr变成{123,2,3,4,5,6,7,8} ,然后是 p++ ,此时 *p 已经是等于arr的第1个元素了了,也就是2。
第四行,在执行 printf 时,括号里的参数是从右往左的顺序进行读取的,也就是说先执行 *(++p) ,
也就是p先加一再指针,指向的是 arr 第2个元素3,然后再执行 *p ,还是3。
最后显示的内容就是:3,3
![](https://i-blog.csdnimg.cn/blog_migrate/c25975a14e0b48817003612c2e442445.jpeg)