数组、指针练习题及解析(含笔试题目讲解)(二)

简介: 数组、指针练习题及解析(含笔试题目讲解)(二)

笔试题3

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);//0x00 00 00 04    0x02 00 00 00
  return 0;
}

程序分析:

这道题在小端存储的计算机上运行的前提下进行讲解。大小端介绍详见前几期博客的讲解连接如下:数据在内存中的存储_清水加冰的博客-CSDN博客

已知计算机为小端存储,那数组a在内存中存储情况就如下图所示:

1转化为16进制就是0x00 00 00 01,在小端机器中存储方式如上图所示。

ptr1为(int*)(&a+1)

&a为int (*)[4]类型,&a+1也是int (*)[4]类型,(int*)(&a+1)就是将&a+1的类型强制类型转换为int*类型(指针类型不同,+1-1所跳过的空间大小不同)。

那ptr1[-1]就等价于:*(ptr1-1),那ptr1-1所指向位置也就是元素4,如下图:

在解引用输出就是0x4(%x输出16进制)。

ptr2 = (int *)((int)a + 1),a是数组首元素地址,将a强制类型转换为int类型,我们先假设a的地址为0x0014ff20,转换为整形,还是0x0014ff20,只不过这里的16进制表示的是数字,那(int)a + 1也就是正常的整数相加,(int)a + 1=0x0014ff21,再将(int)a + 1转换为int*类型,那此时(int)a + 1,也就是a数组首元素地址跳过了一个字节的空间。如下图所示:

然后输出解引用的值,(int)a + 1从整形又被转换为int*类型的指针,整形指针解引用需要4个字节的空间,于是就从(int)a + 1指向的位置向后找4个字节空间的数据,转换为整形。

即00 00 00 02,又因为存储时是小端存储,所以取出时的顺序应该是:02 00 00 00,转换16进制也是0x02 00 00 00

笔试题4

#include <stdio.h>
int main()
{
  int a[3][2] = { (0, 1), (2, 3), (4, 5) };
  int *p;
  p = a[0];
  printf( "%d", p[0]);//1
return 0;
}

分析:

a是一个二维数组,进行了初始化,但它实质上只初始化了三个值,即1,3,5。这里需要注意,初始化使用的是逗号表达式,如果想一行一行初始化应该用{0,1}。所以这里有坑需要看仔细。

 

整形指针变量p=a[0],一般情况下,我们可以把a[0]理解为二维数组的第一行,但这里注意p是一个整形指针,并且赋值的时候没有&a[0],这里的a[0]就相当于是第一行数组的数组名,指向的是数组a[0][0]的地址。p[0]等价于*(p+0),也就是*p,所以结果是1.

笔试题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]);//0xFFFFFFFC     -4
  return 0;
}

分析:

p是一个int(*)[4];类型的指针,p = a,a是一个5行5列的二维数组,那a就是第一行的地址,a是int(*)[5]类型,在赋值时会发生类型转换。我们注意,a走一步是5个整数空间,p走一步是4个整形空间。

我们来看一下p[4][2]的位置,a[4][2]的位置。

它们之间相差了4个字节。我们知道数组在存储地址时是从低地址到高地址,那我们就可以知道&p[4][2] - &a[4][2]以%d的形式输出就是一个-4。

负4的二进制序列为:

原码:10000000000000000000000000000100

反码:11111111111111111111111111111011

补码:1111 1111 1111 1111 1111 1111 1111 1100

当我们以%p(输出地址)的形式打印时,计算机就会将补码当作地址输出

1111 1111 1111 1111 1111 1111 1111 1100

  F      F       F      F      F      F     F      C

也就是0xFFFFFFFC。

笔试题6

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,%d", *(ptr1 - 1), *(ptr2 - 1));//10    5
  return 0;
}

分析:

aa是一个二维数组,&aa取出的是二维数组的地址,&aa+1跳过的是整个二维数组。aa是二维数组首元素的地址,aa+1跳过的是5个整形空间。并且它们都被强制类型转换为int*类型。

ptr1 - 1和ptr2-1也就是ptr1和ptr2向前跳过4个字节(一个整形空间),所以*(ptr1 - 1), *(ptr2 - 1)也就是10和5。

笔试题7

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

分析:

单个字符串时我们可以这样写:char *p=“abcdef”,那当多个字符串呢?

上述题目中就是一个字符指针数组。

a是一个字符指针数组,a[0]存放的是w的地址,a[1]存放的是a(at)的地址,a[2]存放的是a(alibaba)的地址。

char**pa = a;,pa是一个二级指针,pa指向的是a[0],现在pa++之后,pa指向的就是a[1]。

*pa就是a[0],指向的是at中a的地址,而%s输出时需要一个字符串地址才能输出,所以输出结果是at。

面试题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;
}

这道题于上到题目类似,但这道题难度更高一些。

分析:

我们先根据三个变量的初始化画出它们的关系图:

**++cpp,先是cpp++,此时cpp指向的就是cp[1],**就是两次解引用,第一次解引用是cp[1],再解一次引用就是C[2],C[2]是POINT中P的地址,那么输出的就是POINT

*--*++cpp+3,这个看起来很复杂,也间接的考察了优先级,先是++cpp,由于cpp经过了一次++操作,所以这里++操作之后cpp指向的是cp[2],再解引用就是cp[2],然后再对cp[2]进行--操作,这时cp[2]指向的就是C[0],解引用就是ENTER中E的地址,再+3,指向的就是第二个E,输出也就是ER

*cpp[-2]+3,cpp[-2]等价于*(cpp-2),那么*cpp[-2]+3也就可以写成**(cpp-2)+3,这里我们是先进行cpp-2操作,减2之前,cpp指向的是cp[2],cpp-2指向的就是cp[0],进行一次解引用是cp[0]也就是C+3,在解引用一次就是FIRST中F的地址,在+3,就是S的地址,那么输出就是ST

cpp[-1][-1]+1,这里我们在次转换一下,转换为*(*(cpp-1)-1)+1,首先看cpp,在上一个操作中cpp并没有进行++或--操作,所以此时cpp指向的依然是cp[2],cpp-1指向的就是cp[1],解引用就是cp[1](C+2),然后是*(cp[1]-1)+1,cp-1指向的是C[1],解引用后就是NEW中N的地址,+1指向的就是E的地址,所以最终输出是EW


总结

好了本期内容到此结束,希望这些内容能够对您的编程之路有所帮助。最后,感谢您阅读本文并参与博主提供的练习题。如果您有任何疑问或建议,请随时在评论区留言,博主将尽快回复您。感谢阅读!

相关文章
|
6月前
|
存储 监控 算法
关于员工上网监控系统中 PHP 关联数组算法的学术解析
在当代企业管理中,员工上网监控系统是维护信息安全和提升工作效率的关键工具。PHP 中的关联数组凭借其灵活的键值对存储方式,在记录员工网络活动、管理访问规则及分析上网行为等方面发挥重要作用。通过关联数组,系统能高效记录每位员工的上网历史,设定网站访问权限,并统计不同类型的网站访问频率,帮助企业洞察员工上网模式,发现潜在问题并采取相应管理措施,从而保障信息安全和提高工作效率。
89 7
|
9月前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
253 1
|
11月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
295 5
|
11月前
|
网络协议 PHP
软件设计师软考题目解析21 --每日五题
每日五题解析,包括海明码纠错、POP3协议通信模式、中断处理、HTML邮件链接创建和结构化开发方法中的接口设计等知识点。
75 1
|
11月前
|
算法 测试技术
软件设计师软考题目解析24 --每日五题
这篇文章提供了软件设计师软考的每日五题解析,包括测试用例设计、软件维护类型、路径覆盖测试、软件维护工具和系统改进等知识点。
176 0
软件设计师软考题目解析24 --每日五题
|
11月前
|
项目管理
软件设计师软考题目解析20之英语题
软件设计师软考中英语题目的解析和答题技巧,帮助考生攻克英语部分的题目。
136 0
软件设计师软考题目解析20之英语题
|
11月前
|
存储 数据安全/隐私保护
软件设计师软考题目解析下午题01
这篇文章提供了对软件设计师软考下午题目的解析,涉及农业基地信息化管理服务平台的人员管理、基地管理、种植管理、投入品管理和信息服务功能,并要求考生根据上下文描述和数据流图来回答问题。
375 0
软件设计师软考题目解析下午题01
|
11月前
|
安全 算法 网络安全
软件设计师软考题目解析15 --每日五题
这篇文章是关于软件设计师软考的题目解析,包括防火墙功能、网络连接分析、DMZ区服务器类型、拒绝服务攻击特点以及公开密钥加密算法的选择题,旨在帮助考生准备考试。
74 0
软件设计师软考题目解析15 --每日五题
|
11月前
|
前端开发 数据处理
软件设计师软考题目解析23 --每日五题
每日五题解析,涉及结构化开发方法的特点、数据流图的基本加工、MVC体系结构的优点以及模块间耦合类型的判断等知识点。
96 0
|
11月前
|
算法 数据建模 数据库
软件设计师软考题目解析22 --每日五题
每日五题解析,涉及结构化开发方法中的接口设计依据、数据结构和算法设计、数据流图的使用场景、外部实体的识别以及决策树在数据流图中表示复杂条件逻辑的应用。
273 0

推荐镜像

更多
  • DNS