从指针开始变强(四)之超级详细笔试题(二)

举报
lovevivi 发表于 2022/08/12 12:38:06 2022/08/12
【摘要】 @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+12指向 c+3
  解引用后 为c+3本身 
  再次解引用 为 FIRST  可以看作是F的地址
  +3 跳过3个单位 为 ST
  即 ST 

在这里插入图片描述

4.
  cpp[-1][-1]+1
  cpp[-1][-1]等价于 *(*(cpp-1)-1)*(*cpp-1)-1)+13中没有自增自减 所以cpp依旧指向c+11 指向c+2
  解引用后 为c+2本身
  c+2本身减1 为 c+1
  解引用后为 NEW 可以看作是N的地址
  +1为向后跳过1个单位 
  即EW

在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。