一、
1.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;
}
1.2 分析和运行结果
分析:
- 将数组的地址取出来+1跳过一个数组的大小,所以ptr指针指向数组最后一个元素的下一个int类型的起始位置。ptr-1得到最后元素的地址。
- a是数组名,即没有单独放在sizeof中,也没有取地址,所以它代表数组首元素的地址。a+1得到第二个元素的地址,解引用就得到第二个元素。
运行结果:
二、
2.1代码:
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p的值位0x100000。表达式的值分别是多少?
//已知,结构体大小位20字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
2.2 分析和运行结果
分析:
- 这里考察的是指针+1跳过几个字节。
- 第一个printf里面,p指针指针的结构体是20个字节,那它+1就要跳过一个结构体的大小(20个字节)。加完1后就是:0x100014
- 第二个printf里面,p指针被强制转换成了(unsigned long)长整型。那转换后+1就是跳过一个字节。即:0x100001
- 第三个printf里面,结构体指针p被转换成了整型指针,整型指针+1就要跳过4个字节。即:0x100004
运行结果:
三、
3.1 代码
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;
}
3.2 分析和运行结果
图解:
分析:
- 将数组的地址取出来+1跳过一个数组的大小,所以ptr1指针指向数组最后一个元素的下一个int类型的起始位置。ptr1[-1]又可以看成*(ptr-1)。这就是最后一个元素。
- 在第三行中a代表的是数组首元素的地址,将它强转为int,加一就跳过一个字节。所以ptr2就指向上图所示的位置。解引用ptr2就能访问ptr2指向的后四字节的内容。
运行结果:
四、
4.1 代码
int main()
{
int a[3][2] = { (0,1),(2,3),(4,5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
4.2 分析和运行结果
分析:
- 逗号表达式的结果是最后一个元素的内容,即数组a其实只初始化前三个元素。1,3,5。
- 将数组首元素的地址(二维数组的地址是第一个一维数组的地址)赋给指针p。
- p[0] 等价于*(p+0),指针p的类型是整数指针类型的。所以访问一个整型。
运行结果:
五、
5.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;
}
5.2 分析和运行结果
图解:
分析:
- 数组a是一个二维数组,它的类型是int(*)[5]。而p的类型是int(*p)[4]。将数组a的地址赋给数组指针p。那么以指针p的视角来看数组a这个数组时,就如上图所示。
- 地址时由地到高的,指针减指针得到两个指针之间的元素个数。所以&p[4][2] - &a[4][2]就得到-4。
- %d打印就是-4
- %p打印就时-4的补码,即FFFFFFFC
运行结果:
六、
6.1 代码
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;
}
6.2 分析和运行结果
分析:
- ptr1:&aa时取出的二维数组的地址,加1跳过二维数组的地址。
- ptr2:aa代表二维数组首元素的地址即第一个一维数组的地址。加1跳过第一个一维数组。
运行结果:
七、
7.1 代码
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
7.2 分析和运行结果
图解:
分析:
- a数组是字符指针数组,每个元素是字符指针,第一个指针存放的是work这个字符串的地址。第二个指针是存放day这个字符串的地址,第三个字符存放mind字符串的地址。
- pa是指向字符指针数组的指针,它加1是跳过一个字符指针。
- 将数组a的首元素地址赋值给pa,如上图所示。
运行结果:
八、
8.1 代码
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;
}
8.2 分析和运行结果
图解:
运行结果: