笔试题1:
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+1跳到了数组后面第一块地址,将地址给了int* ptr。
*(a+1):a+1 == 首元素地址+1 == 2的地址,*就是2。
*(ptr-1):ptr-1是向后跳过4个字节,它是int类型,ptr-1 == 5的地址,*就是5。
笔试题2:
在x86环境下
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x00000000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
加16进制的1和加10进制的1是一样的
p + 0x1:p是结构体指针,这个结构体有20个字节,p+1就是跳过20个字节(+20)。
(unsigned long)p + 0x1:无符号长整形+1,就是+1,p强转了不是指针。
(unsigned int*)p + 0x1:无符号整形指针+1,是跳过1个字节(+4)。
%p是十六进制显示的
笔试题3:
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);
return 0;
}
ptr[-1]: ptr[-1]==*(ptr-1)==4
*ptr2: ptr2存放的是(int *)((int)a + 1),a是首元素地址转化为int类型+1,地址作为整形+1从内存上看就是跳过1个字节。
笔试题4:
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,0,0}
p存放的是a数组第一行的数组名,p[0]==第一行的首元素==1。
笔试题5:
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[4][2]==*(*(a+4)+2),a是首行地址每行类型是int[5],+4是跳过了20个元素,*(a+4)的类型是int,+2是跳过2个元素。
p[4][2]==*(*(p+4)+2),p就直接看跳过了几个元素,p的类型是int*[4],p+4跳过16个元素,*(p+4)的类型是int,+2跳过2个元素。
&p[4][2] 与 &a[4][2]之间隔了4个元素,&p[4][2] - &a[4][2]==-4,-4以%p的形式打印的是它的补码FFFFFFFC。
笔试题6:
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;
}
*(ptr1-1):&aa+1是aa数组后面第一块内存地址,ptr-1==10的地址,*(ptr-1)==10.
*(ptr2-1):二维数组也是多个一维数组在内存连续存放,aa+1是第一个一维数组的地址,这些数组是int[5]类型,+1跳过20个字节(5个int类型的元素),*(aa+1)==第二个一维数组的数组名(b的地址)。*(ptr2-1)==5
笔试题7:
int main()
{
char *a[] = {"work","at","bubble"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
这种题我们可以画图来理解:
a存放的是w的地址,char**pa=a,就是存放的是a首元素的地址
pa++,是存放的首元素地址+1,pa==a+1
这时*pa拿到的就是"at"a的地址
笔试题8:
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=cp后的图:
**++cpp:++cpp==cp+1,*++cpp==c+2,**++cpp=='p'的地址。打印结果是POINT.
*--*++cpp+3:前面++cpp改变了cpp的值,cpp==cp+1。++cpp==cp+2,*++cpp==c+1,
--*++cpp(这里--不会改变cpp的值)==(c+1)-1==c,*--*++cpp=='E'的地址,E是char类型,地址+3就是跳过三个字节,*--*++cpp+3=="ENTER"中"ER"E的地址。打印结果是ER.
*cpp[-2]+3:cpp==cp+2,cpp[-2]==*(cpp-2)==*(cp)==c+3,*cpp[-2]==*(c+3)=='F'的地址,"FIRST"F地址+3就是S的地址,*cpp[-2]+3=='S'的地址。打印结果是ST
cpp[-1][-1]+1:cpp==cp+2,cpp[-1]==*(cp+1)==c+2,cpp[-1][-1]==*(c+1)=='N'的地址,"NEW",cpp[-1][-1]+1=='E'的地址。打印结果是EW