记一次阿里电面经历

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

项目经历

上来就问我有无大型项目的经历。很差意思,我说无。。算法

。又问我代码量怎样,我说以前有经常刷ACM的题目,因此代码量还可以。编程

C语言变量

问:“函数中的局部变量保存在哪里?” 数组

答:“栈”网络

问:“函数中的局部静态变量保存在哪里?”数据结构

答:“静态区。。”函数

问:“局部静态变量和全局静态变量有不一样吗,不一样点在哪里?”spa

答:“。操作系统

。没太大不一样,都存在一块儿。。”设计

问:“不是问的存储位置。其它方面呢?”

答:“哦,可视的范围不一样。全局静态变量全局可见。局部静态变量仅仅有函数内部可见。”

问:“全局变量和全局静态变量有何不一样”

答:“存的位置是挨着的。要说不一样的话,也是可视范围吧,全局静态变量仅在当前文件内可见,全局变量是该项目所有文件可见。

联合(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指针

问:“声明一个常量指针,指向一个整型。但指向的地址不可变”

哎,这个我知道是重点,也是easy混淆的知识点。前几天我还特意整理了一下。只是,给我点时间我本身慢慢梳理一下可以答好的。他这一问,我才发现我仍是掌握不坚固。

答错了。他又指导了我一下。

正确的答案是:const int * a(int const * 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是用汇编实现的。现在就不知道了。

。)

问:“也不是涉及详细语言,就是内存管理的算法了解吗?”

答:“没看过这方面的不了解。。”

而后问题就结束了。现在想一想他的意思大概是要我从操做系统的知识方面谈一下内存管理的算法,比方扫描一下,哪里未使用的空间就分配出去之类的。


后来问我有什么问题。

我基本没啥问题。问了点弱智问题。

问:“是内推的大家会打电话过来(在某群里找了个内推。

)仍是所有在官方申请实习的。大家都会打电话过来?”

答:“通常所有申请的都咱们会打过去。


---------

后来次日打来第二个电话。二面。。只是二面挂了。。

相关文章
相关标签/搜索