目录
题目一:
int main()
{
int a[5] = { 1,2,3,4,5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
这道题目的结果是什么呢?
这道题目不难分析。我们需要注意的是只有在& 或sizeof(只有数组名)的时候是整个数组,其余时候数组名一般都表示首元素地址。
所以这里&a的类型是int(*)[5],数组指针再加一跳过了整个数组所以是不存在的a[5]的地址,又因为这时的类型是int(*)[5],不是int*,所以需要强制类型转换再赋予ptr.所以,*(a+1)就是a[1],也就是2.*(ptr-1)就是a[4],也即是5.
题目二:
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p=(struct Test*)0x100000;
//假设p 的值为0x100000.如下表表达式的值分别为多少?
//已知,结构体Test类型变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);//跳过一个结构体大小
//0x100000+20-->0x100014
printf("%p\n", (unsigned long)p + 0x1);
//转换成无符号长整型,1,048,576+1-->1,048,577
//0x100001
printf("%p\n", (unsigned int*)p + 0x1);
//跳过4个字节 0x100000+4-->0x100004
return 0;
}
这道题目我们需要注意的是,对于一个类型加一减一就是加上或减去它本身类型的大小,这一点在指针里面尤其重要.所以可以分析一下
p的地址是0x100000加20就是0x100014.
p的地址转换成unsigned int 类型+1就是1,048,577再转化为16进制数,是0x100001.
unsigned int*大小为4个字节,所以0x100000+4==0x100004.
所以答案显而易见:
题目三:
int main()
{
int a[4] = { 1,2,3,4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%#x,%#x", ptr1[-1], *ptr2);//%x是16进制
return 0;
}
这道题目我认为是比较难的一个题目,大家可以思考下,答案是4,2000000。这个结果可能比较出人意料,但是我们要是仔细分析一下就会解得。这道题目需要我们对于数据在内存中的存储有比较深刻的理解。下面我就浅析一下:
题目四:
int main()
{
int a[3][2] = { (0,1),(2,3),(4,5) };
int* p;
p = a[0];
printf("%d", p[0]);//1
return 0;
}
这个题目粗看是很容易看成是3行两列的数组:
然后p是第一行数组名,显而易见就是0.但是答案确是1.为什么呢?我们细看就会发现数组里面不是{}而是(),所以是逗号表达式,取最后一个。所以真实的排布应该是:
所以答案是1.
题目五:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
这道题目也是颇难的。话不多说,开始分析:
首先我们画个图来理解一下在内存中的排布:
这样清晰了不少。
题目六:
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* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
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);
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
这个题目初看真的吓人,但是不必慌张,对于这种比较复杂的指针题,我们需要画出它在内存中的存储,这样方便我们分析.
第一问:
第一问图:
第二问:
温馨提示:在做这道题的时候一定要注意++和--的副作用.
第三问:
第四问:
在第三问里面虽然CPP指向了C+3,但是不是++和--,所以没有副作用,不会改变在第四问还是指向C。
好了,本期的分享就到这里了,剑心谢谢各位停留浏览啦、、