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;
}
答案是:2,5
首先初始化数组,&a表示取出整个数组的地址(切记),&a+1 表示在跳过整个数组,来到下个数组首元素地址的位置,因为要存在整型指针 *ptr中,所以进行强制类型转化;*(ptr-1)表示第一个数组最后一个元素的 位置,解引用也就是5;*(a+1):a既没有sizeof,也没有&a,所以在此a表示首元素的地址,a+1 解引用表示第二个元素,也就是2,所以最终答案是 2, 5;
2. 假设 p 的值为0x100000。如下表达式的值分别是多少?
已知:结构体Test类型的变量大小是20字节;
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//p=0x100000
int main()
{
p = (struct Test*)0x100000;//p 是指针类型,需要强制类型转换为结构体类型;
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
答案是:00100014 00100001 00100004
首先: p 初始化值为0x100000,%p表示打印地址,+0x1表示在基础之上+1;0x是十六进制位的前缀,p是结构体指针,p+1表示加上一个结构体的大小(字符+1表示加上一个字符的大小),题目说明结构体的变量大小为20个字节,p=0x100000+20=0x100014(14的意思是该指针数十六进制位,4*16^0+1*16^1=14)补全十六进制位的8位是0x00100014;
第二个:表示整型p+1,直强制类型转换为整型,就是实实在在的在p=0x100000基础之上+1=0x00100001;
第三个:强制类型转化为一个无符号指针 unsigned int*;无符号指针+1表示跳过一个无符号指针的大小;直接在p的基础之上+4即可=0x00100004;
总结:指针+整数 的大小 取决于 指针的类型;不同指针的类型所加整数值的大小不同;
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;
}
答案是:4 , 2000000
首先:初始化数组a[4];*ptr1的意思是取出a的整个数组地址(&a),在此基础之上+1表示跳过整个数组的大小;来到下一个数组第一个元素的地址; ptr1[-1] 等价于 ptr1-1也就是第一个数组最后一个元素的地址;
a 的32位地址为:01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00;
a表示首元素的地址;a强制类型转换为整型,(int)a+1 直接在整型的基础上+1;来到第二位,强制类型转换为整型,访问8个字节,得到02 00 00 00;
4.
int main()
{
int a[3][2] = { (0, 1 ), ( 2, 3 ),(4, 5)};
int *p;
p = a[0];
printf("%d", p[0]);
return 0;
}
答案是:1;
首先:数组初始化中放的是括号表达式,而不是大括号的数组元素,需要特别注意;
括号表达式的结果是括号里面的最后一个元素,所以在二维数组[3][2]中的元素是1 3 5 0 0 0六个元素;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;
}
答案是: FFFFFFFC, -4
首先:初始化二维数组a[5][5],如下图所示;&a[4][2]:我们先找到a[4],也就是第五行元素,a[4][2]表示第五行下角标为2的元素;如图所示:
把a强制给到指针p,p表示首元素地址;&p[4][2]等价于取出*(*(p+4)+2);而指针p表示数组指针,每个指针指向的数组含有4个元素;然后每四个向后+1;找到p[4]的位置如图所示;解引用得到的元素指向首元素的地址;(p+4)+2得到图中绿色所示的地址;
两个地址相减的结果是两个地址所指向位置之间的元素个数;也就是4;但是显然&a的地址在&p的地址之前,所以是-4;
%p打印地址:得到32位字节的补码形式;-4的补码如下:
100000000000000000000000000000100---原码
1111111111111111111111111111111111011---反码
1111111111111111111111111111111111100---补码 转换成16进制位:每四个是一个F
所以是FFFFFFFC