指针进阶题目演示
指针进阶题目演示
1.求出程序运行结果:
#include<stdio.h>
int main()
{
int[a]={1,2,3,4,5};
int* p=(int*)(&a+1);
printf("%d,%d",*(a+1),*(p-1));
return 0;
}
结果为:
原因:&a+1是给数组地址+1,指针跳过整个数组,跳到5后面的地址,在-1就刚好跳到了5的位置所以解引用为5
a+1是数组名+1,指针指向了2,所以解引用为2
2.补全填空:
#include<stdio.h>
struct Test
{
int Num;
char* pcName;
shortsDate;
char cha[2];
shortsBa[4];
}*p;
//假设p的值为0x100000,则
//p+0x1=0x____?
//(unsigned long)p + 0x1 = 0x____?
//(unsigned int *)p + 0x1 = 0x____?
结果为:
0x100014
0x100004
0x100004
原因:p+1是指p代表的地址加到p的下一个地址,得看p的数据类型,看它需要跳过多少个字节
第一空中p的数据类型是个结构体有20个字节,所以给p加上20个字节后转换为16进制就为0x100014
第二空和第三空中p的数据类型都为4,所以同理可以得出答案
3.求出程序运行结果:
#include<stdio.h>
int main()
{
int a[4] = { 1,2,3,4 };
int* p1 = (int*)(&a + 1);
int* p2 = (int*)((int)a + 1);
printf("%x,%x\n", p1[-1], *p2);
return 0;
}
结果为:
原因:要求*p2首先得知道(int)a+1是什么意思,(int)a指的是将a强制转换为整形,a是数组名会隐式转换为指针,所以这一强制转换之后应该是元素1的首地址,又因为它是小端字节序,所以(int)a代表着存储着1的二进制位01的地址,而这个地址是一个整形数字并不是指针所以+1就是正常的+1,那么这时(int)a+1代表着存储着1的二进制位00的地址,然后再将它强转为地址,占4个字节,此时他代表的应该是00000002,又因为是小端字节序,所以应该为2000000
图示:
4.求出程序运行结果:
#include<stdio.h>
int main()
{
int a[3][2] = { (0,1),(2,3),(4,5) };
int* p;
p = a[0];
printf("%d\n", p[0]);
return 0;
}
结果为:
原因:逗号表达式,inta[3][2]实际={1,3,5},所以p[0]为1(p等于二维数组a的第一行数组的地址)
5.求出程序运行结果:
#include<stdio.h>
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("&a[4][2]=%p,&p[4][2]=%p\n", &a[4][2], &p[4][2]);
printf("&a[4][2]-&p[4][2]=%p,&a[4][2]-&p[4][2]=%d\n", &a[4][2]-&p[4][2], &a[4][2] - &p[4][2]);
return 0;
}
结果为:
原因:a[4][2]和p[4][2]虽然值一样但它们的地址不一样,因为将a赋给p,p是一个数组指针,指向的数组只有4个元素,所以此时p指向的数组可以说是a[5][4],由于数组的内存空间是连续的,而新数组比老数组在每一行都会少1个元素,所以在第五行就少了4个元素,又因为每个元素四个字节,所以二者的地址差16个字节
7.求出程序运行结果:
#include<stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
结果为:
原因:char**pa=a说明pa是此时指向的是a的首元素地址,也就是"work"这个字符串数组的地址,然后+1指的是数组的地址+1,所以从"work"就加到了"at"而不是’o’
8.求出程序运行结果:
#include<stdio.h>
int main()
{
char* c[] = { "enter","new","point","first" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
结果为:
原因:首先要明白c是一个指针数组,cp也是一个指针数组,cpp是一个指针,存的是cp这个数组的首元素地址(&(c+3))
**++cpp:
先给cpp+1,cpp的指向从c+3变到了c+2,然后解引用两次也就是point
*–*++cpp+3:
先给cpp+1,cpp的指向从c+2变到了c+1,然后解引用一次,变成了指向new的数组指针,然后给数组指针-1,等于说是从指向New变成了指向enter,在解引用就变成了enter的数组名,在+3,就指向了enter中的’e’,打印结果为’er’
*cpp[-2]+3:
先给cpp-2,cpp的指向就从c+1变到了c+3,但是并不保存,然后解引用两次,就变成了first的数组名,在+3就指向了first中的’s’,打印结果为’st’
cpp[-1][-1]+1:
先给cpp-1,cpp的指向就从c+1变到了c+2,但是也不保存,然后解引用就变成了指向了point的数组指针,在-1就是数组指针-1,所以就指向了new,在解引用就变成了new的数组名,在+1,就指向了new中的’e’,打印结果为’ew’