题一:
int main()
{
int arr[5]={1,2,3,4,5};
int *ptr=(int*)(&arr+1);
printf("%d %d",*(a+1),*(ptr-1));//运行结果:2 5
return 0;
}
考察知识点:
1.数组名为首元素的地址,给其进行+1操作其实就是指针向后走一步,也就是第二个元素的地址;
2.取地址数组名(&arr)取到的是整个数组的地址,虽然其指向的空间与数组名相同,但其所代表的意义不同。例如:取地址数组名+1,指针会走到数组后边的位置,因此对其进行-1操作,指针会走到数组最后一个元素的位置。
题二:
int main()
{
int arr[4]={1,2,3,4};
int *ptr1=(int*)(&arr+1);
int *ptr2=(int*)((int)arr+1);
printf("%x,%x",ptr1[-1],*ptr2);//运行结果:4,2000000
return 0;
}
考察知识点:
1.对指针使用下标来引用,相当于解引用操作。以上题为例相:(ptr1-1)=ptr[-1];
2.将数组名也就是首元素地址强转为int,在对其进行+1操作,相当于将指针向后移动了一个字节。然后再将其强转为(int)的指针存放在ptr2这个指针中。而解引用操作会访问四个字节。
放到本题来理解就是,用int的四个字节存储了1的值,+1操作过后,指针走到了第二个字节的位置。然后用ptr2来保存这个位置。
具体请看下图:
题三
int main()
{
int a[3][2]={(0,1),(2,3),(4,5)};
int *p;
p=a[0];
printf("%d",p[0]);//运行结果:1
return 0;
}
考察知识点:
1,括号内的逗号表达式结果为最后一个。在本题中(0,1)相当于1;
2.二维数组的数组名相当于第一行的地址。而数组名后只带一个下标则代表第一行的某一列的元素。
题四
int main()
{
int aa=[2][5]={1,2,3,4,5,6,7,8,9,10};
int *ptr1=(int*)(&aa+1);
int *ptr2=(int*)(*(aa+1));
printf("%d,%d",*(ptr1-1),*(ptr2-1));//运行结果:10,5
return 0;
}
考察知识点参考题一
题五
int main()
{
char* c[]={"ENTER","NEW","POINT","FIRST"};
char** cp={c+3,c+2,c+1,c};
char*** cpp=cp;
printf("%s\n",**++cpp);//运行结果:POINT
printf("%s\n",*--*++cpp+3);//运行结果:ER
printf("%s\n",*cpp[-2]+3);//运行结果:ST
printf("%s\n",cpp[-1][-1]+1);//运行结果:EW
return 0;
}
考察知识点:
1.自加或自减(++,–)操作运行后会改变变量本身的值;
下图是对本体指针关系的一个解析:
变量定义完毕后各指针的指向位置
第一个printf执行时和执行后指针的指向位置
第二个printf执行时和执行后指针的指向位置
题六
int main()
{
int arr={1,2,3};
int* p=a;
printf("%d\n",*p++);//运行结果:1
printf("%d\n",*++p);//运行结果:3
return 0;
}
考察知识点:
1.后置的++虽然也可以改变指针的位置,但其返回值不会发生改变。
2.前置的++既改变了指针的位置也改变了其返回值。
因为1,所以在解引用之后打印的仍然是1,但第一个printf语句运行结束之后,指针p已经指向了2的位置。
因为2,所以指针会先指向3然后在解引用打印。