第一题:
#include
#include
#pragma warning (disable:4996)
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
//数组名在和&或sizeof()一起使用时代表整个数组,
//加1之后指向数组最后一个元素后面的位置。
printf("%d,%d,%d\n", *(a + 1), *(ptr - 1), ptr[-1]);
//输出的时候指针-1解引用,就代表5
system("pause");
return 0;
}
第二题:
struct test
{
int num;
char *pcName;
short date;
char ch[2];
short arr[4];
}*p;
假设p的值是0x100000.求下列表达式的值
p+0x1=_______;
(unsigned long)p+0x1=___________;
(unsigned int *)+0x1=___________;
解析:
1.结构体大小为20,p是指针,对指针加减是加减其所指向类型的大小,所以第一个为0x100014;
2.将p强转成无符号整型,整型运算结果为0x100001
3.将p强转成整型指针,指针就是地址大小为4个字节,所以结果为0x100004
第三题:
int main()
{
int a[4]={1,2,3,4};
int *ptr1=(int *)(&a+1);//单独数组名取地址代表整个数组,加1表示“下一个数组的首地址”,也就是4后面的位置
int *ptr2=(int *)((int)a+1);//单独数组名表示首元素的首地址,被强转成整形再加1,此时指向第一个元素第二个字节的位置
//接着再强转成整型指针,解引用的时候需要向后访问4个字节
//也就是第一个元素后三个字节和第二个元素的第一个字节
//同时要考虑大小端会影响数据的存和取
printf("%x,%x\n",ptr1[-1],*ptr2);
return 0;
}
第四题:
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p = a[0];
printf("%d\n", p[0]);
return 0;
}
答案是:1,因为代码中数组的初始化用的是逗号表达式
等价于 int a[3][2] = { 1 , 3 , 5 };
第五题:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("a_ptr=%#p,p_ptr=%#p\n", &a[4][2], &p[4][2]);
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
理解这道题最好的方法就是画图,需要的朋友可以试着画一下
int (*p)[4]定义了一个指针p,指向大小为4个整型的数组,p每次的移动距离为4个整型的
p[4][2] 可以写成 *(*(p+4)+2),p是大小为4个整型的数组指针。
对p解引用就是数组的地址,此时再加2就是数组名+2的意思。
而&p[4][2]-&a[4][2],指向同一内存区域的两个指针相减,结果为两个指针间所经历的元素的个数。
这道题还涉及到负数在内存中的存储,只不过是按%p的形式输出。
!对数组指针解引用代表的是整个数组的地址。
第六题:
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));//这是本题的精华所在,理解(int *)(*(aa+1))
printf("%d %d\n", *(ptr1 - 1), *(ptr2 - 1));
return 0;
aa+1表示第二个元素的地址,而二维数组的元素是一维数组,(aa+1)表示这个作为二维数组第二个元素的一维数组的首地
址,解引用代表整个数组,此时数组名做右值代表的就是首元素的地址,也就是ptr2指向6这个位置。输出时左移一位所以是5
第七题:
#include
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.画图,2.操作符的副作用,3.指针运算
需要注意的是:
指针和++,--运算过之后,在进行下一次运算的话指针的位置已经改变而不是指向最开始的位置。所以++,--就被称为有副
作用的操作符。
下表引用不会改变原来的值。
指针加减整数,是加减其指向类型的大小。