昨天下午(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指针

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

哎,这个我知道是重点,也是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是用汇编实现的。如今就不知道了。

。)

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

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

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


后来问我有什么问题。

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

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

)还是全部在官方申请实习的。你们都会打电话过来?”

答:“一般全部申请的都我们会打过去。


---------

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

posted on 2017-05-18 09:47  yutingliuyl  阅读(291)  评论(0编辑  收藏  举报