快手 C++ 后端研发一二三面面经

一面 1h

(1) 32 位机器,判断以下代码的输出:

int a = 0x1234;
char* p = (char*) &a;
*p == ?
*(p+1) == ?
*(p+2) == ?
int a = 0x00001234;
// 如果是大端序,地址从低到高存储为 00 00 12 34
// 如果是小端序,地址从低到高存储为 34 12 00 00
// 故输出为:
// 大端序:00 00 12
// 小端序:34 12 00

(2) 32 位机器,以下 a 是多少?

int a = (int)(((int *)0) + 4); // 16

(int *)0,相当于是一个 int 型指针,指向地址 0。
(int *)0) + 4 就是对一个 int 指针 + 4。指针每 + 1,相当于后移 n 字节,n 是这个指针指向的变量类型的字节数。这里是 int 指针,一个 int 4 字节,int* + 4 就是后移 16 字节。从地址 0 开始后移 16 字节,指向的地址变成 16。

等价于:

int* p = 0;
p = p + 4;
int a = (int)p; // 强制类型转换,读取 p 的值,即 p 指向的地址

(3) 请找出下面代码中的所有错误

  • GetIntA 里参数应该是引用
  • GetIntB 里应该返回 malloc 创建的变量的地址
void GetIntA(int *p) {
    p = malloc(sizeof(int));
    return;
}

int * GetIntB() {
    int kk;
    return &kk;
}

void main(void) {
    int *p;
    p = NULL; GetIntA(p); *p = 0x22;
    p = NULL; p = GetIntB(); *p = 0x33;
}

(4) 请找出下面代码中的所有错误。说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

#include"string.h"
int main() { 
    char*src="hello,world"; 
    char* dest=NULL; 
    int len=strlen(src); 
    dest=(char*)malloc(len); 
    char* d=dest; 
    char* s=src[len]; 
    while(len--!=0) 
        d++=s--;  
    printf("%s",dest); 
    return 0;
}

改动后的代码(牛客网有原题):

int main() {
    char* src="hello,world";
    char* dest=NULL;
    int len=strlen(src);
    dest=(char*)malloc(len+1); //
    char* d=dest;
    char* s=src+len-1; //;
    while(len--!=0) *(d++)=*(s--); //
    *d = '\0'; //
    printf("%s",dest);
    free(dest); // 
    return 0;
}

(5) 完全随机的抽取 50 人,求这 50 人发生生日冲突的可能性(2 个或更多的人生日相同)有多大?每年都按365天算。

  • 思路:减去所有人都不是同一天生日的概率。上面的式子中,分母是所有人的可能的生日排列情况,分子是 50 个人不在同一天的排列情况
  • 另一种思路:第二个人和第一个人生日不同的概率是 364/365,第三个人和前两个人生日不同的概率是 363/365,以此类推,和上面的公式一样。

(6) 用 C 语言写一个函数,把字符串里面的空格全部去掉,并返回删除的空格的个数,不允许新开辟空间,只能申请简单类型的自动变量。时间复杂度 O(n):

int del_blanks(char* str) {
    int len = strlen(str);
    if (!len) return 0;
    int last = 0;
    for (int i = 0; i < len; i++) {
        if (str[i] == ' ') continue;
        str[last++] = str[i];
    }
    str[last] = '\0';
    return len-last;
}

其他问题:

  • 哈希查找的原理
  • 输入一个 url 到显示网页的过程(网络线程、dns、tcp 三次握手、https 四次握手、传输、解析渲染、对每个链接重复此过程、四次挥手;底层:tcp 拥塞控制流量控制、ip 路由、arp 解析)
  • arp 表的更新方法

二面 40mins

  • top k 问题,时间复杂度估计(快排 O(n),堆 O(nlogk),《剑指offer》原题)
  • 生产者消费者问题,单线程与多线程的情况下分别怎么写?(不会,稀里糊涂做了 30 分钟后结束面试)

三面 1h

  • 目前的 offer 情况,还面了哪些公司
  • 这些公司如果都给你 offer,你会从几个维度进行选择?(地域,公司平台,未来发展,工作内容,薪资)
  • Golang 为什么可以在函数里返回一个函数的地址,在函数外访问?(逃逸分析)
  • 逃逸分析的原理(建议参考维基百科
  • 你用 Golang 的时候有没有遇到一些不好理解的地方(这里我说 err 只能一层层返回 / 没有泛型。然后面试官与我讨论为什么觉得这些特性是必须的)
  • Golang 里返回一个 MyError 类型的 nil,可以用 err != nil 判断吗?(不可以,golang 中的 interface 是一个二元组 (type, value)
  • Golang 的 interface 的 type 和 value 是怎么保存的(不是很确定了)
  • 动态 interface 和静态 interface 有没有听说过?(没有)
  • Golang 的 slice append 扩容原理(slice 是一个指向数组的指针,对应的数组有一个容量 cap;如果 append 时 slice 的 cap 不足以容纳新元素,就会扩容)
  • 扩容的时候是复制原数组的元素吗?(是)
  • 这里会不会有一些问题?(不会,涉及到扩容细节和 golang 的内存分配,参考

到这里一共 20 分钟。接下来是代码题。

(1) 判断以下代码的输出

char buf[4] = {0x12, 0x34, 0x56, 0x78};
*(short*) &buf[3] = ?

在内存中的存储:

地址:101 102 103 104 105
字节:12  34  56  78  ??

也就是 buf[3] 再往后就是其他变量的内存区域了。这时候用 *(short*) 读取从 buf[3] 开始的两字节,结果是 0x78??

(2) 判断结果:

std::string str1 = "123";
std::string str2 = "3333333333";
sizeof(str1) ?= sizeof(str2)

相等,都是 8 个字节。这涉及到 std::string 的实现,内部存储的是指向实际字符串的指针。StackOverflow

(3) this 指针的问题,判断会不会 core:

class A {
 public:
  void print(int n) {
    std::cout << n << std::endl;
  }
};

int main(int argc, char **argv) {
  ((A*)0)->print(4);
}

main() 函数中将地址 0 强制类型转换为 A,然后调用它的 print() 方法。我理解是 print() 里没有用到 this,也就没有对地址 0 解引用,就不会触发异常。

可以了解下静态绑定和动态绑定,C++ 对于非虚成员函数是静态绑定,即不把它绑定到一个特定类型上。

(4) 以下代码会有什么后果?为什么?

char *TestFunc() {
   char buf[1024];
   buf[1026] = 3;
   ...
}

缓冲区溢出,可能会修改函数的参数 / 返回地址... 这里主要考察栈帧的内容:调用一个函数的时候会把哪些信息压倒栈里。推荐阅读《CSAPP》的第 3 章,对这部分内容描述的很清楚。

缓冲区溢出的检测方法(Canary、地址随机化等,同样在《CSAPP》中)。

(5) 海量数据找 topk(无法全部加到内存中):用堆。

(6) 实现 Atoi,要求能处理溢出。这道题也被考了很多次,LeetCode 有原题,主要难点在于如果是 32 位机器该如何判断溢出。

总结

快手的面试体验和其他公司不一样,一二面问的几乎全是 C/C++ 的问题,很少问上层的网络协议等,我答得稀烂。感觉这个可能和部门的工作内容有关。三面的面试官很 nice,答错了会一步一步引导。

#面经##校招##快手##C++工程师#
全部评论
楼主你好,请问你是实习、校招还是社招?
点赞 回复
分享
发布于 2020-09-12 11:49
大佬问下,生产者消费者问题,单线程实现的思路?
点赞 回复
分享
发布于 2020-09-12 13:08
滴滴
校招火热招聘中
官网直投
int a = (int)(((int *)0) + 4); // 0x16 请问这个为什么是16呢,具体原理是什么情况。。
点赞 回复
分享
发布于 2020-09-12 13:42
老哥这是哪个部门啊,也太难了吧
点赞 回复
分享
发布于 2020-09-14 20:47
老哥这三次面试是连着面的么?
点赞 回复
分享
发布于 2020-09-19 19:21

相关推荐

头像
04-15 01:37
已编辑
南昌大学 计算机类
其实二面面经很早就写好了,但是想等出结果了再发,两周过去终于出结果了,春招以来第一次面试的就是厦航,很想去的一家国企,很可惜实力不匹配,人生哪能多如意,在网上也是搜了蛮多线下面的资料,但是都不算很详细,刚好没有通过面试不怕透露什么,写下这篇面经给以后想去厦航的友友一点经验,攒攒人品,#面经##春招前端面经##前端##厦门航空# #软件开发2024笔面经#&nbsp;结束这两周一直盯着手机等待短信的不安。先说笔试:三套卷子,软件研发,硬件开发,还有一套什么忘了,前端开发属于软件研发,卷子内容包括但不限于数据库,python知识,运维知识,大模型知识,前端知识,数据结构,行测逻辑推断,手撕代码手撕代码较为简单1.给一个字符串,长度为n,输出出现超过2/n次的字符2.给一个字符串,反转它3.忘了再说面试,写题过程中喊你去面试(我还想着多看会自我介绍和项目相关的呢),两个面试官一男一女,长相和我的高中老师好像,有点亲切1.&nbsp;自我介绍2.&nbsp;考研了吗,打算怎么办3.&nbsp;为什么选厦航4.&nbsp;你的期望薪资5.&nbsp;说说你的项目6.&nbsp;项目有遇到难点吗,怎么解决的说到这里我就感觉到两个面试官对前端不是很了解,逐渐掌握主动权开始吟唱项目功能实现流程7.为什么选择前端我想在第一线和用户产品打交道—.&nbsp;—后面开始闲聊,比如厦门的房价,你对厦航的了解等等,没有反问环节,我厚着脸问啥时候出结果,面试官说一到二周,不过根据我的调查,一周出的概率太小,10天左右才行(现在看来确实是两周内)面完回来写完笔试已经5点了,大家都走光光了=&nbsp;=就我一个做题做好慢,太折磨了最后分析一下厦航的通过率,二面的13人里通过5人左右,硕士占比高,我一个211本能和9硕同台也是能吹211本≈985硕了hhh,在这期间也是在牛客上向准入职大佬们打听相关的信息,很感谢牛客上大佬们的帮助,最后祝大家春招都能获得心仪的offer,希望那些还待在池子里的朋友们尽快冲出来,避免被kpi面纠缠
点赞 评论 收藏
转发
2 39 评论
分享
牛客网
牛客企业服务