指针笔试题

指针笔试题

1. 练习1

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1)); 2 5
	return 0;
}

分析:

image-20210519110234518

如图所示,&a + 1为数组最后一个元素的邻接位置地址(跳过了整个数组),所以ptr-1为数组最后一个元素,对其解引用为5;

a为数组首元素地址,a+1为数组第二个元素地址,对其解引用为2;

2. 练习2

//此结构体的大小是20个字节(结构体内存对齐)
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
int main()
{
 printf("%p\n", p + 0x1); // 0x100014
 printf("%p\n", (unsigned long)p + 0x1);//0x100001
 printf("%p\n", (unsigned int*)p + 0x1);//0x100004
 return 0; 
}

分析:

由于p为结构体指针(大小为20字节),所以p+0x1相当于0x1000000+14(20的16进制为14),即0x100014;

对于(unsigned long)p + 0x1,p已经被强制转换为unsigned long,p+0x1相当于0x1000000+1,即0x100001;

对于(unsigned int*)p + 0x1,p已经被强制转换为unsigned int*,p+0x1相当于0x1000000+4(指针大小4字节),即0x100004;

3. 练习3

int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);//4
    int *ptr2 = (int *)((int)a + 1);//20 00 00 00
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0; 
 }

分析:

对于ptr1[-1],如下图所示,&a得到数组首元素地址,&a + 1得到数组最后一个元素的邻接元素地址,ptr[-1]相当于指针左移一位,即图示③地址,即为4;

image-20210519111413506

对于*ptr2,如下图所示,a数组地址,将其强转为int后+1,实际指向为下图②所指位置,又因为将其强转为int *,打印时打印四个字节,即下图③,又因为电脑为小端字节序存储,打印时逆序打印,即20 00 00 00;

image-20210519113155935

4. 练习4

int main()
{
	int a[3][2] = { (0, 1),(2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

分析:

首先,由于数组初始化时使用逗号表达式,其每一位为表达式最后一个逗号后的内容,即int a[3][2] = {1,3, 5};

a[0]为第一行数组首地址,将其赋给p,即p为第一行元素首地址,p[0]即第一行第一个元素1;

5. 练习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;
}

分析:

image-20210519131025591

a为数组地址,p=a,所以p也为首元素地址,如上图①所示,a[4][2]位置如上图③所示;

由于数组a为5*5矩阵,但是数组指针p指向的数组大小为4,所以p[4][2]位置如上图②所示;

所以 &p[4][2] - &a[4][2] (指针减指针为中间元素个数),又因为 &p[4][2]在前 &a[4][2]在后,所以按照%d的形式打印结果为:-4,按照%p形式打印,结果为-4在内存中的表示:FFFFFFFC

-4–>内存地址解析:

原码:10000000 00000000 00000000 00000100

反码:11111111 11111111 11111111 11111011

补码:11111111 11111111 11111111 11111100

1111 1111 1111 1111 1111 1111 1111 1100

F F F F F F F C

6. 练习6

int main()
{
	int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&a + 1); //10
	int* ptr2 = (int*)(*(a + 1));//5
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

分析:

image-20210519202700119

&a 表示数组地址,&a + 1表示数组最后一个元素邻接位置地址,如图②所示;

由于a为二维数组,所以其表示数组第一行元素地址,a+1表示第二行元素地址,所以a+1如上图①所示。

7. 练习7

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);//at
	return 0;
}

分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9YxHlpKM-1621435660776)(https://i.loli.net/2021/05/19/ns1D8abSmUlYodP.png)]

如上图所示,指针数组a保存的为"work",“at”,“alibaba” 三个字符串的首地址,pa为二级指针,指向指针数组a的首地址,如图①所示,当pa++时,指针向后移动一个位置,到达如图②所示位置,即指向at首元素的地址的指针,由于打印时按照%s打印,所以打印出“at”;

8. 练习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);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
	return 0;
}

分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fXRqr3xh-1621435660777)(https://i.loli.net/2021/05/19/MmNEc3R6FLZXxlh.png)]

如上图所示,指针数组c保存的为"ENTER",“NEW”,“POINT”,“FIRST” 五个字符串的首地址,如上图①所示;

cp为二级指针数组,指向指针数组c的每个元素(类型为char *)的地址,如上图②所示;

cpp为三级指针,指向二级指针数组的首地址,如上图③所示;

8.1 解析一

对于****++cpp**,三级指针cpp自增后(如上图④所示),再对其进行两次解引用,最终得到POINT的首地址,打印后得到“POINT”;

8.2 解析二

对于***-- * ++cpp + 3**,

  • 由于自增自减运算符优先级高于+ -,所以先对cpp进行++运算,(由于经过上一步自增,cpp已经指向下图①位置)如下图②所示;

image-20210519210557224

  • 接着对其地址值解引用(* ++cpp),得到c+1,但又因为对其自减(-- (* ++cpp)),得到c,起始状态下,其指向下图①所指位置(c+1),经过运算后,其指向下图②所指位置(c),接着对其进行解引用操作*(-- (* ++cpp)),得到元素E的地址;

    image-20210519211054010

  • 现在指针已经指向元素E的地址,如下图①所示,将其+3后指针移动到如下如②所示位置,将其按照%s打印后,结果为 ER

image-20210519211730950

8.3 解析三

对于*cpp[-2] + 3

  • cpp[-2],首先将指针后移两个位置,如下图②所示,并得到(c+3)的地址,如下图③所示;
  • *cpp[-2] ,再将其解引用得到FIRST首元素F的地址,如图④所示;
  • *cpp[-2] + 3,将其+3相当于指针后移三位,即指向S,如图⑤,将其按照%s打印后,结果为 ST

image-20210519212328862

8.4 解析四

对于cpp[-1][-1] + 1

  • cpp[-1]为将三级指针cpp位置前移一位的结果,其地址入下图①,结果如下图②所示;
  • cpp[-1][-1]如下图④所示,得到N的地址;
  • cpp[-1][-1] + 1,将N的地址右移一位,得到E的地址,如下图⑤所示,将其按照%s打印后,结果为 EW

image-20210519213920370

17-1621435660780)]

8.4 解析四

对于cpp[-1][-1] + 1

  • cpp[-1]为将三级指针cpp位置前移一位的结果,其地址入下图①,结果如下图②所示;
  • cpp[-1][-1]如下图④所示,得到N的地址;
  • cpp[-1][-1] + 1,将N的地址右移一位,得到E的地址,如下图⑤所示,将其按照%s打印后,结果为 EW

image-20210519213920370

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值