从指针开始变强(四)之超级详细笔试题(二)
【摘要】 @TOC 前言发现了新的整理解释的方法–代码块真的好用啊 一、练习题 1.练习1#include<stdio.h>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;}` 1. &a+1 ...
@TOC
前言
发现了新的整理解释的方法–代码块
真的好用啊
一、练习题
1.练习1
#include<stdio.h>
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;
}`
1. &a+1
a作为数组名 取地址后 数组名为整个数组的地址
&a+1为跳过整个数组下一块空间的地址
%x代表最终结果以16进制输出
而在内存中以16进制表示的
VS中在内存以小端存储的
1 --- 00 00 00 01
2 --- 00 00 00 02
3 --- 00 00 00 03
4 --- 00 00 00 04
小端存储是以低字节位放在低地址处 高字节放在高地址处
内存中表示为
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
ptr1[-1]等价于 *(ptr1-1)
整形指针减一跳过4个字节 又因为是整形指针取4个字节
即 04 00 00 00
转换为正常表示为 00 00 00 04
2. (int)a+1
a作为数组名 没有单独放在sizeof内部 也没有取地址
数组名作为首元素地址 即1的地址
强制转换为整形 +1
例: a为 0x20--->32
32+1------>33
33------->0x21
字节数加1
内存中表示为
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
a原来为 01 00 00 00
*ptr2为 00 00 00 02
*ptr2转换正常为 02 00 00 00
2.练习2
#include<stdio.h>
int main()
{
int a[5][5];
int(*p)[4];
p=a;
printf("%p,%d",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);
return 0;
}
a为二维数组的数组名 没有单独放在sizeof内部 也没有取地址
数组名作为首元素地址 二维数组的首元素地址为第一行的地址
应用数组指针接受即 int(*)[5] 而p虽然只能存放4个元素
但依旧可以传进去 p+1 跳过4个整形 a+1跳过5个整形
a[4][2]为第5行第三个元素
p[4]作为第五行的数组名 取地址后 数组名为整个第五行的元素
即 &p[4][2]为 p本身跳跃的第五行第三个元素的地址
需要注意的是 数组随着下标的增大 地址由低变高
故 p[4][2]所在为低地址
a[4][2]所在为高地址
&p[4][2]-&a[4][2] 为负
地址相当于指针 指针-指针为两者之间的元素个数 即 4
结果为 -4
-4 原码 10000000 00000000 00000000 00000100
反码 11111111 11111111 11111111 11111011
补码 11111111 11111111 11111111 11111100
而地址在内存中 以补码形式表现出来
即 11111111 11111111 11111111 11111100
转换成16进制
FF FF FF FC
3.练习3
#include<stdio.h>
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",*(ptr1-1),*(ptr2-1));
return 0;
}
1. &aa aa作为整个二维数组的数组名 取地址后
数组名作为整个二维数组的元素
取得是整个二维数组的地址
&aa+1 为跳过整个数组下一块空间的地址
*(ptr1-1) 整形指针减一 跳过4个字节
即指向 10
结果为10
2. *(aa+1) aa作为二维数组的数组名
没有单独放在sizeof内部 也没有取地址
数组名作为首元素地址 二维数组的首元素地址是 第一行的地址
aa+1 为第二行的地址 解引用后为代表第二行的元素
第二行的元素可以看作是第二行的数组名
数组名 没有单独放在sizeof内部 也没有取地址
数组名为首元素地址 即6的地址
*(ptr2-1) 整形指针减一 指针向左移移位
即 5
结果为5
4.练习4
#include<stdio.h>
int main()
{
char*c[]={"ENTER","NEW","POINT","FIRST"};
char**cp[]=(c+3,c+2,c+1,c};
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. **++cpp
cpp作为三级指针 接收cp
cp为一个二级指针数组 cp作为数组名 没有单独放在sizeof内部
也没取地址 cp数组名作为首元素的地址 即c+3的地址
++cpp cpp指向c+2
**++cpp cpp作为c+2的地址 c+2本身指向POINT
即为POINT
2. *-- * ++cpp+3
因为运算符优先级问题
应先算 ++ 再算解引用 再算 -- 再算解引用 最后再加3
cpp在1中自加 指向c+2
再次++ 指向c+1 解引用找到c+1本身
c+1本身-- 变成 c
而不是cpp-- 所以cpp依旧指向c+1
再次解引用 为ENTER 可以看作是E的地址
+3向后三个单位 为ER
即为ER
3. *cpp[-2]+3
cpp[-2]等价于 *(cpp-2)
即**9cpp-2)+3
cpp在2中指向c+1 减2指向 c+3
解引用后 为c+3本身
再次解引用 为 FIRST 可以看作是F的地址
+3 跳过3个单位 为 ST
即 ST
4.
cpp[-1][-1]+1
cpp[-1][-1]等价于 *(*(cpp-1)-1)
即 *(*cpp-1)-1)+1
在3中没有自增自减 所以cpp依旧指向c+1
减1 指向c+2
解引用后 为c+2本身
c+2本身减1 为 c+1
解引用后为 NEW 可以看作是N的地址
+1为向后跳过1个单位
即EW
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)