• C++面试八股文:聊一聊指针?


    某日二师兄参加XXX科技公司的C++工程师开发岗位第17面:

    面试官:聊一聊指针?

    二师兄:好的。

    面试官:你觉得指针本质上是什么?

    二师兄:这要从内存地址开始说起了。如果有一块容量是1G的内存,假设它的地址是从0x000000000x3fffffff,每一个字节都对应一个地址。当我们声明一个变量并初始化它时:

    int a = 42;
    

    二师兄:操作系统会分配一块容量为4(sizeof(int))的地址,这块内存的首地址是0x00001000(假设),结束地址是0x00001003,在申请的这4个字节上放入42。当我们对这个变量取地址时,

    int a = 42;
    int* p = &a;
    

    二师兄:操作系统会再分配一块内存,这块内存的大小是sizeof(int*),这块内存的起始地址是0x00002000(假设),结束地址是0x00002003(32位操作系统),然后将&a取到的起始地址0x00001000放入0x00002000-0x00002003中。并将刚分配的这块内存的起始地址赋给p

    指针

    二师兄:当我们对p操作时,是对0x00002000-0x00002003这块内存操作,当我们对*p(解引用)操作时,是对0x00001000-0x00001003这块内存操作。

    二师兄:回到问题,我觉得指针的本质就是内存地址。虽然指针指向一块内存地址,但它同时也是一个变量,也可以对指针取地址。如果对指针取地址,同样可以得到一个内存地址(如0x00002000),如果把这个内存地址存起来,那么指向这个内存地址的变量的类型就是二级指针(int**)。

    面试官:好的。在0x00002000-0x00002003这块内存中,我们放入了一个地址是0x00001000,但是并没有这个地址的长度。只知道一个地址而不知道长度,怎么能把数据取出来?

    二师兄:这主要是因为p的类型是int*,当对p解引用时,编译器知道了解引用的结果是int类型,所以从0x00001000往后读取4个字节(sizeof(int)),并按照当前CPU的模式(考虑大小端)把这四个字节组成一个int类型的变量。

    面试官:malloc函数你知道吧,返回的类型是void*,在free的时候怎么知道这块内存的大小的呢?

    二师兄:额。。这个还不太清楚。。

    面试官:没关系,今天就到这里,回去等通知吧。

    让我们来看看让二师兄折戟的这个问题:

    malloc函数返回的类型是void*,在free的时候怎么知道这块内存的大小的呢?

    这里牵扯到mallocfree的实现方式,不同的厂商实现的方式不尽相同。以ptmalloc为例,当使用malloc申请size = 16的内存时,malloc会从内存池中分配一块sizeof(chunk)+16长度的内存。chunk段保存了一些前后chunk的信息,也保存了这块内存的大小(16)。malloc函数返回的地址是0x00001000,而在free(0x00001000)时,free函数会用0x00001000减去特定值(sizeof(chunk)),得到chunk的起始地址,从chunk中获取这块内存真正的尺寸,从而完成free的任务。抛开内存的利用率不说,这是一个非常美妙的实现!

    malloc

    好了,今日份面试到这里就结束了。关注我,每天带你学习一个C++小知识!

    关注我,带你21天“精通”C++!(狗头)

  • 相关阅读:
    [Python]`threading.local`创建线程本地数据
    SIGIR 2021 | UPFD:用户偏好感知假新闻检测
    ECRS工时分析软件:全面提升生产效率和产能管理的利器
    【遥感变化检测综述】—《多时相遥感影像的变化检测研究现状与展望》
    Arduino与Proteus仿真实例-简单信号频率计数仿真
    Rust 构建跨平台 GUI 的新选择
    LeetCode-907. 子数组的最小值之和【单调栈,数组】
    微信的9个隐藏功能,我不允许还有人不知道!
    MongoDB性能分析
    路由器端口转发
  • 原文地址:https://www.cnblogs.com/binarch/p/17488343.html