目录
题目1:
题目2:
题目3:
题目4:
题目5:
题目6:
题目7:
题目1:
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
解析:
a是数组首元素的地址,类型为int*,+1跳过一个元素,再解引用就是第二个元素。
&a是整个数组的地址,+1跳过整个数组,再强制类型转化为int*类型,-1就是数组最后一个元素的地址,解引用后就是最后一个元素。
答案:
2,5
题目2:
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解析:
p是一个指针,类型是struct Test*,是由十六进制数字0x100000强制类型转换为struct Test*类型所得到的。
0x1就是1,p+1就是跳过一个元素,一个结构体的大小是20个字节,地址就加20,变成0x00100014.将p强制类型转化为unsigned long类型的值再加1,就是单纯的数学运算,结果是0x00100001.将p强制类型转化为unsigned int*类型的指针,+1跳过4个字节就是0x00100004
题目3:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}
解析:
a数组是一个二维数组,但是初始化的是用的括号,括号的结果是逗号表达式的结果,也就是最后一个逗号后面的表达式的值。这个数组初始化的值前三个分别是1,3,5,其余默认是0
a[0]是第一行的数组名,也就是第一行首元素的地址,p[0]可以写成*p,所以就是第一个元素。结果就是1.
题目4:
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
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;
}
解析:
二维数组的元素在内存中也是连续排列,所以a数组也可以看成一个元素个数为25个的一维数组。
a是第一行的地址,类型是int *[5],p是int *[4],&p[4][2]就可以看成第(3 * 4 + 3)个元素的地址,&a[4][2]就是第(3 * 5 + 3)个元素的地址,指针相加减得到的是地址之间的元素个数,也就是4个元素,但是值是-4,分别以十六进制和十进制打印,整数在内存中是以补码的形式存储,所以-4的十六进制,和十进制分别是
//1000 00000000 00000000 00000000 0011 原码
//1111 11111111 11111111 11111111 1100 反码
//1111 11111111 11111111 11111111 1101 补码
//F F F F F F F C
题目5:
#include <stdio.h>
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));
return 0;
}
&aa是整个数组的地址,+1跳过整个数组转化为int*类型后 ,-1向前跳过4个字节,也就是数组最后一个元素的地址,再解引用就是 10
*(aa+1)就是aa[1],第二行的数组名,第二行首元素的地址,转化为int*后,-1就是第一行最后一个元素的地址,再解引用就是5.
题目6:
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
解析:
a数组是一个元素类型为char*类型的地址,a是数组名,也是数组首元素的地址,也就是一个二级指针,因为它指向的元素也是一个指针,pa++,就变成了第二个元素的地址,解引用后就是字符串at。
题目7:
#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;
}
解析:
printf("%s\n", **++cpp);
//cpp是cp数组首元素的地址,也就是c+3的地址
//++cpp,就变成了c+2的地址
//*++cpp,就是c+2
//c是"ENTER"的地址
//c+2就是"POINT"的地址
//再解引用就是"POINT"
//打印POINT
printf("%s\n", *-- * ++cpp + 3);
//++cpp,就变成了c+1的地址
//*++cpp,就是C+1,
//c+1就是"NEW"的地址
//再--,就是"ENTER"的地址
//再*就是"ENTER",首字符的地址,然后+3,就是"E"的地址,
// 最后打印ER
printf("%s\n", *cpp[-2] + 3);
//cpp[-2]就是*(cpp-2)
//cpp-2就是C+3的地址
//*后就是C+3
//再*就是"FIRST",然后加3,就是"S"的地址,
//打印ST
printf("%s\n", cpp[-1][-1] + 1);
//cpp[-1][-1]就是*(*(cpp-1)-1)
//cpp-1就是C+2的地址,
//*后就是C+2,-1,就是C+1
//C+1是"NEW"的地址,*后就是"NEW",+1就是"E"的地址,
//打印EW