当前位置: 首页 > wzjs >正文

集团网站建设工作方案优化站点

集团网站建设工作方案,优化站点,免费搭建手机网站,小程序助手指针和数组的面试题 面试题一面试题二(指针算数)题目回顾关键概念计算三个表达式1. p 0x12. (unsigned long)p 0x13. (unsigned int*)p 0x1 最终答案验证思路总结 面试题三面试题四逗号表达式 面试题五面试题六2. ptr1 的计算 面试题七题目分析关键点…

指针和数组的面试题

  • 面试题一
  • 面试题二(指针算数)
      • 题目回顾
      • 关键概念
      • 计算三个表达式
        • 1. `p + 0x1`
        • 2. `(unsigned long)p + 0x1`
        • 3. `(unsigned int*)p + 0x1`
      • 最终答案
      • 验证思路
      • 总结
  • 面试题三
  • 面试题四
    • 逗号表达式
  • 面试题五
  • 面试题六
      • 2. `ptr1` 的计算
  • 面试题七
      • 题目分析
      • 关键点
      • 逐步解析
        • 1. `printf("%s\n", **++cpp);`
        • 2. `printf("%s\n", *--*++cpp + 3);`
        • 3. `printf("%s\n", *cpp[-2] + 3);`
        • 4. `printf("%s\n", cpp[-1][-1] + 1);`
      • 最终答案
      • 内存布局变化总结
      • 总结

我们之前了解了指针和数组的一些基本常识,如果大家对这块还不太熟悉可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/146522555?spm=1011.2415.3001.5331

https://blog.csdn.net/qq_67693066/article/details/146526324?spm=1011.2415.3001.5331

今天我们主要来看看一些面试题:

面试题一

int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的结果是什么?

我们可以运行一下看看结果:
在这里插入图片描述
我们画个图来一步一步分析:
在这里插入图片描述首先是 int *ptr = (int *)(&a + 1);
在这里插入图片描述然后是printf( “%d,%d”, *(a + 1), *(ptr - 1));
在这里插入图片描述
在这里插入图片描述

面试题二(指针算数)

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

题目回顾

我们有一个结构体 Test,其大小为 20 字节,并定义了一个指向该结构体的指针 p,初始值为 0x100000。然后,在 main 函数中打印了三个表达式的值:

printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);

我们需要计算这三个表达式的值。


关键概念

  1. 指针算术(Pointer Arithmetic)

    • 对指针进行加减运算时,步长取决于指针指向的类型的大小。
    • 例如,p + 1 实际上是 p + sizeof(*p)
  2. 类型转换的影响

    • 将指针转换为整数(如 unsigned long)后,加减就是普通的数值运算。
    • 将指针转换为其他类型的指针(如 unsigned int*)后,步长会按新类型的大小计算。
  3. %p 格式说明符

    • 用于打印指针的值,通常以十六进制显示。

计算三个表达式

1. p + 0x1
  • pstruct Test* 类型,指向的结构体大小为 20 字节
  • 指针算术:p + 1 = p + sizeof(struct Test) = 0x100000 + 20
  • 需要将 20 转换为十六进制:
    • 20(十进制)= 0x14(十六进制)。
  • 因此:
    • p + 0x1 = 0x100000 + 0x14 = 0x100014
2. (unsigned long)p + 0x1
  • (unsigned long)p 将指针 p 转换为无符号长整型,此时它只是一个普通的整数 0x100000
  • 整数加法:0x100000 + 1 = 0x100001
  • 注意:%p 可以打印任何地址值,即使是从整数转换来的。
3. (unsigned int*)p + 0x1
  • (unsigned int*)pp 转换为 unsigned int* 类型。
  • unsigned int 的大小通常是 4 字节(取决于平台,但题目未说明,假设为 4 字节)。
  • 指针算术:(unsigned int*)p + 1 = (unsigned int*)p + sizeof(unsigned int) = 0x100000 + 4
  • 4(十进制)= 0x4(十六进制)。
  • 因此:
    • (unsigned int*)p + 0x1 = 0x100000 + 0x4 = 0x100004

最终答案

运行程序后,三个 printf 的输出分别为:

0x100014      // p + 0x1
0x100001      // (unsigned long)p + 0x1
0x100004      // (unsigned int*)p + 0x1

验证思路

  1. p + 0x1
    • pstruct Test*,结构体大小 20 字节 → p + 1 = 0x100000 + 20 = 0x100014
  2. (unsigned long)p + 0x1
    • 转换为整数后直接加 1 → 0x100000 + 1 = 0x100001
  3. (unsigned int*)p + 0x1
    • unsigned int* 步长为 4 字节 → 0x100000 + 4 = 0x100004

总结

  • 指针加减:步长由指针指向的类型决定。
  • 强制类型转换
    • 转整数 → 直接数值运算。
    • 转其他指针 → 按新类型的步长运算。
  • 本题的关键是清楚不同类型指针的步长。

面试题三

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;
}

这里的ptr[-1]和上面的*(ptr - 1)是一个意思:
在这里插入图片描述
在这里插入图片描述

面试题四

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

逗号表达式

这里注意一下坑,数组初始化时用了逗号表达式, 逗号表达式会计算所有子表达式,但最终取 最后一个值。

例如 (0, 1) 的值是 1,(2, 3) 的值是 3,(4, 5) 的值是 5。

所以这个三行两列的数组实际上有效的数字只有三个:1,3,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;
}

这里有的平台上运行会报错,会报类型不匹配的错误,如果报错,记得强转一下:
在这里插入图片描述
这里,a会发生强转,由int (*) [5] 强转为 int ()[4] 的类型,这暗含了一个条件p指向的数组,一行只有4个元素

  • p[4][2]a[4][2] 的地址计算方式不同:
    • a[4][2]a 的第 4 行第 2 列,地址为 &a[0][0] + 4 * 5 * sizeof(int) + 2 * sizeof(int)
    • p[4][2]p 的第 4 行第 2 列,地址为 &p[0][0] + 4 * 4 * sizeof(int) + 2 * sizeof(int)
  1. 地址计算

    • &a[4][2]
      • aint [5][5]a[4][2] 的偏移量 = 4 * 5 + 2 = 22int
    • &p[4][2]
      • pint (*)[4]p[4][2] 的偏移量 = 4 * 4 + 2 = 18int
    • 由于 p = a&p[0][0] = &a[0][0],所以:
      • &p[4][2] - &a[4][2] = (&a[0][0] + 18) - (&a[0][0] + 22) = -4(以 int 为单位)。
  2. 指针减法

    • 指针减法的结果是两个地址之间的元素个数(int 为单位)。
    • -4%p 打印时会被转换为无符号数(通常是补码表示),以 %d 打印则是 -4

在这里插入图片描述

面试题六

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));return 0;
}

这道题和前面思路其实大同小异:


int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

aa 是一个 2 行 5 列的二维数组,内存布局如下:

aa[0][0] = 1   aa[0][1] = 2   aa[0][2] = 3   aa[0][3] = 4   aa[0][4] = 5  
aa[1][0] = 6   aa[1][1] = 7   aa[1][2] = 8   aa[1][3] = 9   aa[1][4] = 10

2. ptr1 的计算

int* ptr1 = (int*)(&aa + 1);

&aa 是整个数组的地址(类型是 int (*)[2][5])。
&aa + 1 会跳过整个 aa 的大小(2×5=10 个 int),指向 aa 末尾的下一个位置。
(int*) 强制转换为 int*,所以 ptr1 指向 aa 之后的位置。

ptr1 - 1 指向哪里?
ptr1 指向 aa 末尾之后,ptr1 - 1 回退 1 个 int,指向 aa[1][4](即 10)。
• 因此 *(ptr1 - 1) 的值是 10


int* ptr2 = (int*)(*(aa + 1));

aa 是二维数组名,在表达式中退化为指向第一行的指针(类型 int (*)[5])。
aa + 1 指向第二行(aa[1])。
*(aa + 1) 解引用得到第二行的数组(类型 int[5]),再退化为指向 aa[1][0] 的指针(int*)。
• 因此 ptr2 指向 aa[1][0](即 6)。

ptr2 - 1 指向哪里?
ptr2 指向 aa[1][0]ptr2 - 1 回退 1 个 int,指向 aa[0][4](即 5)。
• 因此 *(ptr2 - 1) 的值是 5
在这里插入图片描述

面试题七

题目分析

这段代码定义了一个多层指针结构,并通过指针运算打印字符串:

const char *c[] = { "ENTER","NEW","POINT","FIRST" };
const char **cp[] = { c + 3, c + 2, c + 1, c };
const 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

关键点

  1. 指针结构

    • c 是一个字符串数组,存储 4 个字符串的地址。
    • cp 是一个指针数组,存储 c 中元素的地址(c + 3 指向 "FIRST"c + 2 指向 "POINT",依此类推)。
    • cpp 指向 cp 的首元素。
  2. 初始内存布局

    c[0] = "ENTER" (地址 &"ENTER")
    c[1] = "NEW"   (地址 &"NEW")
    c[2] = "POINT" (地址 &"POINT")
    c[3] = "FIRST" (地址 &"FIRST")cp[0] = c + 3 = &c[3] = &"FIRST"
    cp[1] = c + 2 = &c[2] = &"POINT"
    cp[2] = c + 1 = &c[1] = &"NEW"
    cp[3] = c + 0 = &c[0] = &"ENTER"cpp = &cp[0]
    
  3. 指针运算规则

    • ++cppcpp 指向 cp 的下一个元素。
    • *cpp:解引用 cpp,得到 cp[i]
    • **cpp:解引用 cp[i],得到 c[j](即字符串地址)。
    • +n:对字符串指针进行偏移,跳过前 n 个字符。

逐步解析

1. printf("%s\n", **++cpp);
  • 初始状态
    • cpp 指向 cp[0]
  • ++cpp
    • cpp 现在指向 cp[1]
  • *cpp
    • cp[1] 的值是 c + 2(即 &c[2])。
  • **cpp
    • c[2]"POINT"
  • 输出
    POINT
    
2. printf("%s\n", *--*++cpp + 3);
  • 当前状态
    • cpp 指向 cp[1]
  • ++cpp
    • cpp 现在指向 cp[2]
  • *++cpp
    • cp[2] 的值是 c + 1(即 &c[1])。
  • --*++cpp
    • *cpp&c[1],对其减 1 后变为 &c[0]
    • 注意:cp[2] 的值被修改为 &c[0](副作用)。
  • *--*cpp
    • c[0]"ENTER"
  • + 3
    • "ENTER" + 3 跳过前 3 个字符,指向 "ER"
  • 输出
    ER
    
3. printf("%s\n", *cpp[-2] + 3);
  • 当前状态
    • cpp 指向 cp[2](因为上一步 ++cpp 后未移动)。
  • cpp[-2]
    • cpp 指向 cp[2]cpp[-2] = *(cpp - 2) = cp[0]
  • *cpp[-2]
    • cp[0] 的值是 c + 3(即 &c[3]),解引用后是 c[3] = "FIRST"
  • + 3
    • "FIRST" + 3 跳过前 3 个字符,指向 "ST"
  • 输出
    ST
    
4. printf("%s\n", cpp[-1][-1] + 1);
  • 当前状态
    • cpp 指向 cp[2]
  • cpp[-1]
    • *(cpp - 1) = cp[1]
  • cpp[-1][-1]
    • cp[1] 的值是 c + 2(即 &c[2]),cp[1][-1] = *(c + 2 - 1) = c[1] = "NEW"
  • + 1
    • "NEW" + 1 跳过前 1 个字符,指向 "EW"
  • 输出
    EW
    

最终答案

运行程序后,输出为:

POINT
ER
ST
EW

在这里插入图片描述

内存布局变化总结

操作cpp 指向cp 的值变化关键解引用
初始cp[0]cp[0]=&c[3], cp[1]=&c[2], cp[2]=&c[1], cp[3]=&c[0]
**++cppcp[1]无变化cp[1]c[2] = "POINT"
*--*++cppcp[2]cp[2]&c[1] 改为 &c[0]cp[2]c[0] = "ENTER""ER"
*cpp[-2] + 3cp[2]无变化cp[0]c[3] = "FIRST""ST"
cpp[-1][-1] + 1cp[2]无变化cp[1]c[1] = "NEW""EW"

总结

  • 指针运算优先级++ > * > +
  • 副作用*--*++cpp 修改了 cp[2] 的值(从 &c[1] 变为 &c[0])。
  • 数组下标等价性
    • cpp[-1] = *(cpp - 1)
    • cpp[-1][-1] = *(*(cpp - 1) - 1)
http://www.dtcms.com/wzjs/308269.html

相关文章:

  • 学做网站卖东西去哪学外贸网站建设案例
  • 网站建设 成都5g网络优化工程师
  • 网站建设价格兴田德润i网址多少南昌seo推广
  • 如何做网站的图片滑动块seo常用方法
  • wordpress纯文章模板奉化网站关键词优化费用
  • 城阳做网站找哪家好免费的黄冈网站有哪些平台
  • 广州企业网站排名下载百度安装
  • 交易猫假网站制作互联网广告代理商
  • php 政府网站源码google seo教程
  • wordpress建站必须选择主题百度收录关键词查询
  • 中国建设大数据网站搜索引擎优化方案
  • 网站上的验证码怎么做的搜索引擎优化的目标
  • 传媒公司做网站条件腾讯企点客服
  • 登录功能网站怎么做seo教程 seo之家
  • 做动态网站 和数据库交互类似凡科建站的平台
  • c2c网站制作seozou是什么意思
  • 海尔集团网站是怎么做的市场调研方法有哪几种
  • 淘宝客网站如何做推广网络营销软件商城
  • 尼尔的h版是那个网站做的网络营销这个专业怎么样
  • 上海网站建设市场分析seo百度百科
  • 网站改标题关键词描述seo怎么去优化
  • 杭州网站建设慕枫网络推广途径
  • wordpress微信采集器百度快照怎么优化排名
  • 沂水建设局网站企业管理培训课程
  • 网站规划文档上海优化网站
  • 内江规划建设教育网站整合营销方案
  • 网站编辑前端可以做吗站长seo
  • 镇江哪里做网站免费推广的渠道有哪些
  • 镇江市质监站网址培训班招生方案有哪些
  • 做企业网站费用温州seo博客