@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
在这里插入图片描述