记一次阿里电面经历

原写作时间 2015-03-20

昨天下午(3/19)三点多钟,接到了一个杭州的电话,是阿里的。问我是否方便聊聊,我说我在上课,四点下课。然后他就四点多钟的时候又打了一次过来。

项目经历

上来就问我有无大型项目的经历,不好意思,我说无。。。又问我代码量如何,我说之前有经常刷ACM的题目,所以代码量还可以。

C语言变量

问:“函数中的局部变量保存在哪里?”
答:“栈”
问:“函数中的局部静态变量保存在哪里?”
答:“静态区。。”
问:“局部静态变量和全局静态变量有不同吗,不同点在哪里?”
答:“。。没太大不同,都存在一起。。”
问:“不是问的存储位置,其他方面呢?”
答:“哦,可视的范围不同。全局静态变量全局可见,局部静态变量只有函数内部可见。”
问:“全局变量和全局静态变量有何不同”
答:“存的位置是挨着的,要说不同的话,也是可视范围吧,全局静态变量仅在当前文件内可见,全局变量是该项目所有文件可见。”

联合(union)

问:“知道联合吗?”
答:“union”
问:“和结构体有何不同?”
答:“联合的每个成员的拥有共同的起始地址(共享存储空间),而结构体为每一个成员单独分配空间。”
问:“union这样设计的目的是什么(union有何用途)?”
下面我就赶快头脑风暴了一下。。绞尽脑汁地的表达自己的拙见。该部分内容你可以无视,我觉得自己扯得也有点远。。
“这样设计节省内存空间,有时候在某个特定的情况下,我们只需要用的某种特定的类型,如何像结构体那样则浪费了存储空间。在以前的时候Linux编程(POSIX)中IP地址的结构体(struct in_addr)就是一个联合(也可能是结构体成员是联合),比如成员是4个元素char数组,两个元素的short数组,或一个int等等,这样我们就能依据不同的网络类型(A类、B类、C类)来自由的获取该地址的网络号或主机号(比如,要获得一个网络的网络号。若是一个A类地址,我们就读取char数组第一个元素。B类地址我们就读取short的第一个元素来)”
当然了现在的struct in_addr 里面实际上只是包含一个整型的结构体了。不是联合了。上面关于in_addr和联合的说法是从《UNP》上看来的。。

算法

大数相加的算法

问:“如何实现两个数的相加(超过了long long这些的范围了)?”
答:“用一个字符数组来存储数字,然后依次遍历每个字符,通过减‘0’字符的方法转换为数字,再逐位相加。。。”
这是比较经典的大数算法。但他其实没等我说完就打断我了
问:“这样当然可以,但是这种方法效率很低,有没有高效的方法”
答:“不会了”
问:“再想半分钟”
答:“真的不会了(对自己也是无语,求网友告知算法)”

其他算法

问:“你还了解哪些算法”
答:“大部分是学数据结构涉及到的算法,BFS,DFS,最小生成树,最短路径等等。hash也算一种算法吧,还有排序算法。其他的比如像并查集这种数据结构也算吧。”
关于算法我没敢多提,因为我也怕他深入地问下去,好久没搞算法了,这次没准备,肯定会跪。
不过他也没深入的问下去

书籍

问:“你没有项目经验,那你读过什么经典书籍吗?”
答:“C++ primer,Think in C++也读过一点。(其实读过一点的经典书籍还有很多。。)”

const指针

问:“声明一个常量指针,指向一个整型,但指向的地址不可变”
哎,这个我知道是重点,也是容易混淆的知识点,前几天我还特地整理了一下。不过,给我点时间我自己慢慢梳理一下可以答好的,他这一问,我才发现我还是掌握不牢固。
答错了。他又指导了我一下。
正确的答案是: int * const a。
const int * a(int const * a) 是指向的整型的值不可变,指针本身可变。


总结一下,速记方法:关键的是const与星号()的位置。int永远在星号左边的。记成“反转”就行了。可以忽略到int。那么就只有两种形式
const * a和
const a。表面上const * a const在星号前面应该是修饰指针的,但是要反转记忆一下,它是修饰变量的。即变量是常量。

  • const a表面上,cosnt在a前面应该是修饰变量的,实际上它是修饰指针的,即地址是常量不能变。
    以上仅仅是速记的方法,并不是C语言设计者的设计意图。。。

内存对齐

问:“比如你malloc了一段内存,它的地址不是内存对齐的,如何实现8字节的内存对齐?”
答:“一个预处理的那个#pragma可以实现(#pragma pack(8))”
问:“这是用编译器来实现,有没有软件方式?”
接下来是在他的提示下,我大概猜测了一下回答的。
答:“先判断malloc的内存地址是不是内存对齐的”
问:“如何判断?”
答:“8字节对齐,那么内存地址应该是8的倍数,可以%8(对8求余)”
问:“这会涉及到除法运算,效率比较低。”
答:“那就用位操作,可以按位与,前面几位是0后面三位是1,哦,我说的是二进制(十进制7)。然后判断值是否为0”
问:“如果结果是没有对齐,该如何对齐呢?”
接下来就完全是我的臆测了
答:“那就给这个地址指针加一下,差多少就加多少,可能还要依据指针类型进行一些转换。”(答的不好。不过他也没提反对意见,就下一题了


后来我自己手动敲了一下代码,需要注意的问题是指针是不能直接进行求余或位操作的,进行指针到int类型的强制类型转换是失败的。可选方案如下:
如果是C++的话,使用reinterpret_cast

long pp = reinterpret_cast<long>(p); // p 是char *类型  

如果pp是int型(reinterpret<int>(p))则会报错提示丢失精度(gcc 64位)。
二面的时候面试官又问了同样的问题,不过问的细节更多,他说可以用static_cast<>来转换指针为整型。我后来试了一下发现不可以。。会报错的。所以我尝试了reinterpret_cast<>
如果是C++的话,就:

int pp = reinterpret_cast<int>(p); // p是char *类型  

C语言虽然没这个功能,但其实要想比较指针地址是否是8的倍数,实现还是比较简单的,指针类型是无法指针做&操作的。但是我们可以进行一个小转换:

//a 是malloc的返回值,char *类型  
if ((a - (char *)0) & 7)  
{  
....  
}  

当然这段代码C++也可以用。
要注意的是malloc的返回值最好要强制类型转换为 char *:

// 比如分配一百的个字符的空间。  
char *p = (char *)malloc(sizeof(char)*(100+8)); // 多分配8个字节的空间,为了以后的偏移留足空间。  

虽然理论上malloc的返回值可以转化为任意指针类型比如:int *。但是要注意到指针的加减操作,所偏移的单位是指向类型的大小。比如:

// 如果p是int *类型  
p += 1; // p向后偏移1*4个字节(int是4个字节)  
// 如果p是char *类型  
p += 1; // p向后偏移1*1个字节(char是1个字节)  

很明显char *类型的指针偏移的精确度更高。这也是为什么我们通常把malloc返回值转换为char *而不是int *的原因。


回调函数

问:“C++中如何实现回调函数”
回调函数,挺熟的名字,callback。。。但是具体是个什么意思还真不好说。记得在安卓里面见到过。就扯了一下安卓。。
问:“那么在C++中该如何实现呢”
接下来,确实也是运气。脑袋里冒出个函数指针,就脱口而出了,说了个一般的函数指针用法。貌似说对了。
答:“函数指针吧,先什么一种类型的函数的函数指针,然后你可以自己去实现这种类型的函数,然后再把这个函数作为参数传递给函数中(参数是函数指针的函数)。”

内存分配原理

问:“有没有看过内存分配管理的源码?比如malloc之类的。”
答:“没有啊,那大概是汇编吧”(记得大概是Linus说过早期的malloc是用汇编实现的。现在就不知道了。。)
问:“也不是涉及具体语言,就是内存管理的算法了解吗?”
答:“没看过这方面的不了解。。”
然后问题就结束了。现在想想他的意思大概是要我从操作系统的知识方面谈一下内存管理的算法,比如扫描一下,哪里未使用的空间就分配出去之类的。

后来问我有什么问题。我基本没啥问题。问了点弱智问题。
问:“是内推的你们会打电话过来(在某群里找了个内推。。)还是所有在官方申请实习的,你们都会打电话过来?”
答:“一般所有申请的都我们会打过去。”


后来第二天打来第二个电话,二面。。不过二面挂了。。


后记 2017-09-24

这算是我人生第一次面试吧。让我认识到了我的不足,在面试结束后得以针对性地补齐只是短板。失败并不可怕,怕的不是失败,而是不能发现自己的问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 题目类型 a.C++与C差异(1-18) 1.C和C++中struct有什么区别? C没有Protection行为...
    阿面a阅读 7,631评论 0 10
  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,960评论 0 7
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,711评论 0 4
  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,282评论 0 6
  • 这一周,或者说这半年,生活极其有规律:七点左右起床,如果田田没醒,我就一个人去跑步,顺便买菜买早餐;如果田田醒了,...
    田田何田田阅读 189评论 0 0