第一题:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
//程序的结果是什么?
解析:
1.a有五个元素分别是1,2,3,4,5.
2.将a的地址取出来+1跳过整个数组,再强转成 int*为首元素的地址
3.所以*(a+1)a的地址是首元素的地址+1为第二个元素的地址
4.(*ptr-1)是存放下一个数组的首地址-1便得到了这个数组最后一个元素的地址
所以最后的结果为2 5.
第二题:
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
p=(struct Test *)0x100000;
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解析:
1.*p为结构体的指针变量
2.p是指向结构体+1跳过20个字节,0x100014(注意十六进制的转化)
3.先将p强制转化为长整型+1就是加了个整数1 0x100001
4.先将p强制转换成一个int* +1相当于加4 0x100004
注:%p是以地址的形式打印16进制数,不是打印地址。最高有效位前面的0
%x是以十六进制打印,会省略最高位前面的0。
第三题:
int main()
{
int a[4] = { 4,3,2,1 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);
return 0;
}
解析:
1.ptr1先将a的地址取出来,+1跳过整个数组,再将这个地址强制转换成int*
2.ptr2先将a的首元素地址强制转换成int型加上数字1再强制转换成int*相当于跳过一个字节
3.打印:ptr1[-1]相当于*(ptr1+(-1)结果跳回4.
4.打印:ptr2由于只跳过去一个字节所以 结果为3 00 00 00
注意:小端存储的形式是低权重位在低地址处,高权重位在高地址处,但是取得时候要按照正常得排序去取03是这个整形的最高地址为所以取出来的是0x3 0 00 00 00
第四题:
#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;
}
解析:
1.首先数组里面存放的是逗号表达式 0,1取最终值为1,2,3取最终值为3,4,5取最终值为5
2.将数组首元素的地址放入*p中
3打印:p[0]相当于*(p+0)的值为1
注意:
(0,1)这种形式为逗号表达式不是数组元素{ }才是数组元素
第五题:
#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;
}
解析:
1.int a为一个五行五列的数组
2.int *p是一个能指向四个元素的数组指针。(*p相结合代表的是指针,指向整形有4个元素的
地址)
3.p等于a相当于p指针指向a(一次跳过四个元素)
4.&p[4][2]相当于*(*(p+4)+2),&a[4][2]相当于(*(*a+4)+2)
5.所以%d打印为-4,%p是以地址的形式打印十六进制,所以要将-4转化为16进制
6为ff ff ff fC
第六题
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;
}
解析:
1.ptr1 为跳过整个数组之后的地址强制转换成int*
2.ptr2 为跳过第一行的地址解引用第二行首元素的地址强制转换为int*
3.ptr1 -1 得到最后一个元素的地址解引用等于10
4.ptr2-1 得到第一行最后一个元素的地址解引用等于5
5.所以输出 10 和 5
第七题
include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
解析:
1.char *a[ ] a先与方块结合表示一个数组,再与指针结合表示是一个指针,表示指针数组
2.将w的地址放入pa
3.pa++跳过一个元素
4.打印为 at
第八题
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;
}
1.c先于[ ]结合表示是一个数组,再于*结合表示是个指针(指针数组)
存的是e的地址 n的地址 p的地址 f的地址
2.char **cp[ ]表示存放的是char* 类型的指针
分别指向f的地址 p的地址 n的地址 c的地址
3.char *** cpp指向的是cp首元素的地址
4.**++cpp,cpp先++得到第二个元素,解引用得到c+2,再解引用得到了p的的地址,%s向后打印得到了point
5.*--*++cpp+3 先++得到了第三个元素,解引用得到了c+1,再-- c+1变为c ,再解引用得到了e的地址,加三得到e的地址向后%s打印er
6.*cpp[-2]+3 cpp[-2]相当于*(cpp-2)得到了第一个元素的内容,再解引用得到了f的地址+3得到了s的地址,向后打印st
7.cpp[-1][-1]+1 cpp[-1][-1]相当于*(*(cpp-1)-1) cpp-1得到了第二个元素的地址,*得到cpp的内容c+2 再-1为c+1,解引用为n的地址,+1为e的地址,向后打印为ew
注意++ -- 会实际改变原本内容,表达式不会改变原本的内容