现在的位置: 首页 > 综合 > 正文

笔试面试总结(1)

2019年11月21日 ⁄ 综合 ⁄ 共 14881字 ⁄ 字号 评论关闭

1、TCP三次握手

2、堆排序的实现
3、memcpy
4、数据库DB、数据库系统DBS、数据库管理系统DBMS三者之间的关系是?
数据库系统DBS包括数据库DB和数据库管理系统DBMS!!
5、产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
6、缺页中断:FIFO和LRU最近最久
计算个数的时候,一定要将开始为空填满的时候,也要算进去
7、广度优先遍历的实现
8、结构体所占内存大小的计算
 使用gcc默认对齐规则的情况下,下列两个数据结构的sizeof各是多少?()
struct FirstStruct{
char a;
uint64_t b;
uint32_t c;
uint32_t d;
};
struct SecondStruct{
char a;
uint32_t b;
uint32_t c;
};
A、17,13 B、24,16 C、24,24 D、32,16
9、将数学表达式转化为后缀形式
10、在操作系统的生产者消费者问题中,能否将生产者进程wait(empty)和wait(mutex)语句交换?为什么?
11、请指出二叉树后序遍历栈操作算法的关键,并给出最简单的算法思路。
12、C语言的数据在内存中以补码形式存放,根据题目的条件,可将x、y、z的值由十进制转为二进制补码。
  x为int型,且在32位的机器上运行,因此x字长为32位,转换成二进制为0000 0000 0000 0000 0000 0000 0111 1111,再转换成十六进制为0000007FH。
  y为short型,且在32位的机器上运行,因此y字长为16位,转换成二进制为1111 1111 1111 0111(取反加1),再转换成十六进制为FFF7H。
  z为int型,且在32位的机器上运行,因此z字长为32位,z=x+y=127-9=118,转换成二进制为0000 0000 0000 0000 0000 0000 0111 0110,再转换成十六进制为00000076H。
 
13、

每增加一个度为 4的结点,叶子增加3个,

每增加一个度为 3的结点,叶子增加2个,

每增加一个度为 2的结点,叶子增加1个,

每增加一个度为 1的结点,叶子数不变。

原来只有一个根。所以 1 + 3*20+2*10+1=82

13、
最大流最小割定理:最大流等于最小割容量;
如图最小割容量为 15+19+12=46
14、跳跃链表
15、在计算机系统中,数值一律用补码来表示(存储)
16、孤儿进程和僵尸进程
17、linux内存屏障浅析
18、图的算法,哪些采用贪心算法
19、ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库系统,必需要具有这四种特性,否则在事务过程(Transaction
processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。
20、一个无规律的数组,只允许遍历一遍,求方差
设最终的和为T,平均值为m,各个数为X0到XN方差的公式是:
((m - x0)^2 +……+(m - xN)^2) / N
= ((T/N - x0) ^2 +……+(T/N - xN) ^2)/N
= ((T - N*x0)^2/N^2+……+(T - N * xN)^2/N^2)/N
= ((T^2 - 2N * x0 + N^2 * x0^2) +……+ (T^2 - 2N * xN + N^2 * xN^2))/N^3
= (N*T^2 - 2N * T + N^2 * (x0^2 + ……+ xN^2))/N^3
显然一次循环可以搞定,循环中计算T 和 x[i]的平方和即可,循环结束后
即可完成整个算式的计算了。
21、进程的挂起与阻塞
阻塞是由于进程所需资源得不到满足,并会最终导致进程被挂起
 
进程挂起的原因并不一定是由于阻塞,也有可能是时间片得不到满足,挂起状态是进程从内存调度到外存中的一种状态,若在就绪态时,从内存调出到外存中,就是就绪挂起态,若在阻塞态时,从内存调出到外存中,就转换成了阻塞挂起态
22、10G个数找中位数
23、海量数据找中位数:
24、
25、求最大流
26、从一道百度面试题到分析输入url到页面返回的过程(或者查询返回过程)
27、内存访问速度通常在50ns到80ns范围内,SSD硬盘的访问速度一般是SATA硬盘的一千多倍
几十纳秒,几十微秒,几十毫秒
28:笔试面试(3)阿里巴巴2014笔试题详解(9月22北京)
29、某网络的IP地址空间为192.168.5.0/24,采用定长子网划分,子网掩码为255.255.255.248,则该网络的最大子网个数、每个子网内最大可分配地址个数各位(C)
   A、8,32   B、32,8    C、32,6    D、8,30 
192.168.5.0/24 表示24位是掩码每个网中,第一个IP地址(即主机部分全部为0的IP)和最后一个IP(即主机部分全部为1的IP)不能分配给主机使用,所以每个子网的可用IP地址数为总IP地址数量减2;
30、如何判断一个图中是否存在回路 
31、判断有向图是否存在回路,利用(A)方法最佳
   A、拓扑排序                    B、求最短路径
   C、求关键路径                  D、广度优先遍历 
知识点:拓扑排序 
32、阿里巴巴有相距1500km的机房A和B,现有100GB数据需要通过一条FTP连接在100s的时间内从A传输到B。已知FTP连接建立在TCP协议之上,而TCP协议通过ACK来确认每个数据包是否正确传送。网络信号传输速度2*108m/s,假设机房间带宽足够高,那么A节点的发送缓冲区可以设置为最小(A)
   A、18M         B、12M        C、6M        D、24M 
解析: 
   TCP协议原理:TCP每发送一个报文段,就启动一个定时器,如果在定时器超时之后还没有收到ACK确认,就重传该报文。 
   如图所示,数据包由A的缓冲区发往B,B在收到数据包以后,回发一个ACK确认包给A,之后A将该数据包从缓冲区释放。因此,该数据包会一直缓存在A的缓冲区,直到一个ACK确认为止。题目要求在100s内发送100GB数据,网络的传输速率至少是1G/s,某个数据包n在A中缓存的时间就是数据包n从A到B,再加上该数据包的ACK从B到A的时间:2*1500km/(2*108m/s)=1.5*10-2s,该段时间A中缓存的数据量至少是1G/s*1.5*10-2s约为15M 
33、设某文件经内排序后得到100个初始归并段(初始顺串),若使用多路归并排序算法,且要求三趟归并完成排序,问归并路数最少为(D)
   A、8           B、7           C、6          D、5 
解析:m个元素k路归并的归并趟数s=logk(m),代入数据:logk(100)≦3 
34、文件分配表FAT是管理磁盘空间的一种数据结构,用在以链接方式存储文件的系统中记录磁盘分配和追踪空白磁盘块,整个磁盘仅设一张FAT表,其结构如下所示,如果文件块号为2,查找FAT序号为2的内容得知物理块2的后继物理块是5,再查FAT序号为5的内容得知物理块5的后继物理块是7,接着继续查FAT序号为7的内容为“Λ”,即该文件结束标志,


假设磁盘物理块大小为1KB,并且FAT序号以4bits为单位向上扩充空间。请计算下列两块磁盘的FAT最少需要占用多大的存储空间?
(1)一块540MB的硬盘                 (2)一块1.2GB的硬盘 

解析:(1)磁盘块大小为1KB,540MB的硬盘可以分成540MB/1KB=5.4*105个磁盘块,因此至少需要5.4*105<220个编号,需要20bit存储空间
         (2)同理,1.2G至少需要1.2*106<221个编号,为21bit,由于FAT序号以4bits为单位向上扩充,因此需要24bit存储空间
34、开放地扯法: 公式 Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)  其中,m为哈希表的表长。di 是产生冲突的时候的增量序列 
再哈希法:设计二种甚至多种哈希函数,可以避免冲突,但是冲突几率还是有的。
链地址法:拉出一个动态链表代替静态顺序存储结构,可以避免哈希函数的冲突,不过缺点就是链表的设计过于麻烦,增加了编程复杂度。此法可以完全避免哈希函数的冲突。 
建立一个公共溢出区
35、下面说法错误的是: 
         A: CISC计算机比RISC计算机指令多 
        B: 在指令格式中,采用扩展操作码设计方案的目的是为了保持指令字长不变而增加寻址空间 
        C:增加流水线段数理论上可以提高CPU频率 
        D:冯诺依曼体系结构的主要特征是存储程序的工作方式 
解析:  
A:RISC设计原则:指令条数尽可能少,一般为几十条指令;寻址方式尽可能少;采用等长指令,不管功能复杂的还是简单的指令,均用同一长度;设计尽可能多的通用寄存器 
B:在指令格式中,采用扩展操作码设计方案的目的是为了保持指令字长不变而增加指令操作的数量 
C:流水线设计可最大限度地利用了CPU资源,使每个部件在每个时钟周期都在工作,从而提高了CPU的运算频率。CPU采用级数更多的流水线设计可使它在同一时间段内chǔ理更多的指令,有效提高其运行频率。 
答案:B 
36、不属于冯诺依曼体系结构必要组成部分是: 
        A:CPU B: Cache C:RAM D:ROM 
解析: 
    冯诺依曼体系结构: 
37、你认为可以完成编写一个C语言编译器的语言是: 
A:汇编 B:C语言 C:VB D:以上全可以 
解析:汇编肯定的可以的;任何语言都是可以自解释的,也就是可以用自己编写编译器解释自己,所以B也是对的;C应该也可以,不过答案已经出来了。 
答案:D 
38、关于C++/JAVA类中的static成员和对象成员的说法正确的是: 
A:static成员变量在对象构造时候生成 
B: static成员函数在对象成员函数中无法调用 
C: 虚成员函数不可能是static成员函数 
D: static成员函数不能访问static成员变量 
解析: 
    A:static成员变量在类的定义时初始化,不可以在对象的构造函数中初始化 
    B:static成员函数在对象成员函数中可以调用,同属于一个类作用域 
    C:static成员函数不可以声明为const和virtual 
    D:static成员函数只能访问static成员变量 
答案:C 
39、袋中有红球,黄球,白球各一个,每次任意取一个放回,如此连续3次,则下列事件中概率是8/9的是:
A: 颜色不全相同     B:颜色全不相同    C:颜色全相同    D:颜色无红色
解析:
颜色不全相同:1 - ( 1/3 * 1/3 * 1/3 ) * 3 = 8/9
颜色全不相同:1/3 * ( 1 - 1/3 ) * ( 1 - 1/3 - 1/3 ) = 2/9
颜色全相同:    ( 1/3 * 1/3 * 1/3 ) * 3 = 1 /9
颜色无红色:    ( 1 - 1/3 ) * ( 1 - 1/3 ) * ( 1 - 1/3 ) = 8/27
答案:A
40、关于排序算法的以下说法,错误的是:
A: 快速排序的平均时间复杂度O(nlogn),最坏O(N^2)
B:堆排序平均时间复杂度O(nlogn),最坏O(nlogn)
C:冒泡排序平均时间复杂度O(n^2),最坏O(n^2)
D:归并排序的平均时间复杂度O(nlogn),最坏O(n^2)
答案:D
解释:归并排序的平均时间复杂度O(nlogn),最坏O(nlogn)
41、已知二叉树前序遍历和后序遍历如何求中序遍历?
这样的题是不能得到唯一的二叉树来的!
如: 
树A:有结点1,2,3,2是1的左孩子,3是2的右孩子 
树B:有结点1,2,3,2是1的右孩子,3是2的左孩子 

则A,B的前序都是123,后序都是321,但A的中序是231,B的中序是132
前序遍历和后序遍历是不能确定唯一的二叉树
42、宿舍内5个同学一起玩对战游戏。每场比赛有一些人作为红方,另一些人作为蓝方。请问至少需要多少场比赛,才能使任意两个人之间有一场红方对蓝方和蓝方对红方的比赛? 
解析:
一次划分中,某方可以有1人,另一方有4人或某方有2人,另一人有3人。
要使任意两个人之间有一场红方对蓝方和蓝方对红方的比赛,假设5个同学为A,B,C,D,E,相当有有向图的5个节点,任意两个节点间有两个方向的边连接。
即总的节点关系有(5个节点中选取两个节点)A(5,2)=5*4=20个关系。
而一次比赛(一次划分)能够生成的关系(一方两人一方三人的划分)c(2,1)*c(3,1)=2*3=6或者(一方四人一方一人的划分)c(4,1)*(c(1,1)=4*1=4,
所以一场比赛(一次划分)最多生成的关系次数为6
所以需要20/6=3.33..即至少需要4场比赛
答案:4场,分别是AB-CDE、ACD-BE、BCE-AD、DE-ABC
43、一个有10亿条记录的文本文件,已按照关键字排好序存储。请设计算法,可以快速的从文件中查找指字关键字的记录
答案:建立B/B+树,通过指针指向偏移量,快速定位。
44、两颗二叉树T1和T2,T1的节点数是百万数量级,T2的节点数一千以内,请给出判断T2是否是T1子树的可行算法。
首先想到的是递归,但是T1的数量级太大,递归会导致栈溢出,于是以非递归实现。
45、字符串 alibaba 有多少个不同的排列
思路:先有序排列:aaabbli。首先递归a(aabbli), b(aaabli), l(aaabbli) ,i(aaabbl)...依次交换不相同的。
只计算个数的话,就用:A(7,7) / (A(3,3)*A(2,2)) = 420
46、 某校园网用户无法访问外部站点210.102.58.74,管理人员在windows 操作系统下可以使用(       )判断故障发生在校园网内还是校园网外。
  A. ping 210.102.58.74            B. tracert 210.102.58.74
  C. netstat 210.102.58.74          D. arp 210.102.58.74 
47、 第一题:7公斤米,50克砝码,200克砝码各一个,称1350克米问最少要多少次,并编程回答。
我答,6次,可能一开始会想到 1350/250 + 2 = 7次,说明贪心无效。我不知道我的方法是不是很笨,用了递推,或者你可以看成是动态规划。转化一下题目的意思就是1克和4克砝码,问多少次称出27克大米,F[N]代表N克大米最少需要多少次。
则有:
F[N]=min{F[N-1],F[N-4],F[N-5]}+1
代码如下:
intfindmin(int weight)
{
         int v= weight/50;
         int f[150];
         f[0]=0;f[1]=1;f[2]=2;f[3]=3;f[4]=1;
         if (v<5) return f[v];
         int i;
         for (i=5;i<=v;i++)
                   f[i]=min(f[i-1]+1,f[i-4]+1,f[i-5]+1);
         return f[v];
}
 
注:我一开始愣了很久,我在想,称好的大米可以作为砝码来用吗??这样就是另一种问题了吧。
附加:
如果天平能做为平衡工具的话,两次平分到1750克,然后两次量出200克,1750-400就是1350克了。。。四次。。。。

解答题第一题: 
第一次:200+50,称出250g 第二次:200+250,称出450 第三次:200+450,称出650 
共称出1350g
48、sizeof()那点事
49、内存分配
50、OSI的七层模型
51、请列举下不同进程之间共享数据的方式(至少举出三种)
    1、文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址间一块内存那样来对待
    2、共享内存(Shared Memory)实际就是文件映射的一种特殊情况
    3、命名管道(Named Pipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道
    4、邮件槽(Mailslots)提供进程间单向通信能力,任何进程都能建立邮件槽成为邮件槽服务器
    5、剪贴板(Clipped Board)为不同应用程序之间共享不同格式数据提供了一条捷径
    6、动态连接库(DLL)中的全局数据可以被调用DLL的所有进程共享
52、请描述下TCP和UDP的差别,并且各列举出一个上层协议。
     TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
 
    UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
 
    经常使用“ping”命令的原理就是向对方主机发送UDP数据包,ftp等就是使用到的TCP协议
53、写出new和malloc、delete和free的区别
从面向对象来说,new/delete和malloc/free的区别是:malloc/free只是单纯的进行内存空间的分配和释放,而使用new/delete时,不仅分配了内存空间,若new/delete的是一个类,还会调用类(经测试,基本类型好像不会进行默认初始化)的构造函数或析构函数。
  简单来说,两者的区别主要有:
  1. malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符,与”+“、”-“、”*“、”/“有一样的地位。
  2. new/delete是可以重载的,而重载之后,就成为了函数。
  3. malloc在申请内存的时候,必须要提供申请的长度,而且返回的指针是void*型,必须要强转成需要的类型。
  4. 当new/delete在类中被重载的时候,可以自定义申请过程,比如记录所申请内存的总长度,以及跟踪每个对象的指针。
  5. new/delete,其实内部也调用了malloc/free。
  两者的共同点有:
  1. 都必须配对使用,防止内存泄露。
  2. 都可用于申请动态内存和释放内存,都是在堆中分配内存。
  3. free和delete可以释放NULL指针。
54、写两个继承类,解释虚表指针和虚表的作用
每一个类都有虚表。
  虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类有3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。
  派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
55、写出static的用法和作用
static 是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。函数内部定义的变量,在程序执行到它的定义处时,编译器为它在
  栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至
  下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的
  访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。 需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装
  性,即要求此成员隐藏在类的内部,对外不可见
56、写出计算机的存储器层次,及原因
     以处理器为中心,计算机系统的存储依次为寄存器、高速缓存、主存储器、磁盘缓存、磁盘和可移动存储介质等7个层次。距离处理器越近的存储工作速度越高,容量越小。其中,寄存器、高速缓存、主存储器为操作系统存储管理的管辖范围,磁盘和可移动存储介质属于操作系统设备管理的管辖范围。
57、写出对windows中的句柄的理解
     所谓句柄实际上是一个数据,是一个Long (整长型)的数据。
   句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。
58、当前计算机系统一般会采用层次结构存储数据,请介绍下典型计算机存储系统一般分为哪几个层次,为什么采用分层存储数据能有效提高程序的执行效率?
     所谓存储系统的层次结构,就是把各种不同存储容量、存取速度和价格的存储器按层次结构组成多层存储器,并通过管理软件和辅助硬件有机组合成统一的整体,使所存放的程序和数据按层次分布在各种存储器中。目前,在计算机系统中通常采用三级层次结构来构成存储系统,主要由高速缓冲存储器Cache、主存储器和辅助存储器组成。
     存储系统多级层次结构中,由上向下分三级,其容量逐渐增大,速度逐级降低,成本则逐次减少。整个结构又可以看成两个层次:它们分别是主存一辅存层次和cache一主存层次。这个层次系统中的每一种存储器都不再是孤立的存储器,而是一个有机的整体。它们在辅助硬件和计算机操作系统的管理下,可把主存一辅存层次作为一个存储整体,形成的可寻址存储空间比主存储器空间大得多。由于辅存容量大,价格低,使得存储系统的整体平均价格降低。由于Cache的存取速度可以和CPU的工作速度相媲美,故cache一主存层次可以缩小主存和cPu之间的速度差距,从整体上提高存储器系统的存取速度。尽管Cache成本高,但由于容量较小,故不会使存储系统的整体价格增加很多。
     综上所述,一个较大的存储系统是由各种不同类型的存储设备构成,是一个具有多级层次结构的存储系统。该系统既有与CPU相近的速度,又有极大的容量,而成本又是较低的。其中高速缓存解决了存储系统的速度问题,辅助存储器则解决了存储系统的容量问题。采用多级层次结构的存储器系统可以有效的解决存储器的速度、容量和价格之间的矛盾。
59、Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免?
     一个进程在调用exit命令结束自己的生命的时候,其实它并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其完全销毁)。
     在Linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。它需要它的父进程来为它收尸,如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,那么它就一直保持僵尸状态,如果这时父进程结束了,那么init进程自动会接手这个子进程,为它收尸,它还是能被清除的。但是如果如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是为什么系统中有时会有很多的僵尸进程。

  避免zombie的方法: 
      1)在SVR4中,如果调用signal或sigset将SIGCHLD的配置设置为忽略,则不会产生僵死子进程。另外,使用SVR4版的sigaction,则可设置SA_NOCLDWAIT标志以避免子进程僵死。 
      Linux中也可使用这个,在一个程序的开始调用这个函数 signal(SIGCHLD,SIG_IGN);  
      2)调用fork两次。
      3)用waitpid等待子进程返回.
60、简述Unix/Linux系统中使用socket库编写服务器端程序的流程,请分别用对应的socket通信函数表示
  TCP socket通信

服务器端流程如下:

1.创建serverSocket

2.初始化 serverAddr(服务器地址)

3.将socket和serverAddr 绑定 bind

4.开始监听 listen

5.进入while循环,不断的accept接入的客户端socket,进行读写操作write和read

6.关闭serverSocket

客户端流程:

1.创建clientSocket

2.初始化 serverAddr

3.链接到服务器 connect

4.利用write和read 进行读写操作

5.关闭clientSocket

这个列表是一个Berkeley套接字API库提供的函数或者方法的概要:
     socket() 创建一个新的确定类型的套接字,类型用一个整型数值标识,并为它分配系统资源。
     bind() 一般用于服务器端,将一个套接字与一个套接字地址结构相关联,比如,一个指定的本地端口和IP地址。
     listen() 用于服务器端,使一个绑定的TCP套接字进入监听状态。
     connect() 用于客户端,为一个套接字分配一个自由的本地端口号。 如果是TCP套接字的话,它会试图获得一个新的TCP连接。
     accept() 用于服务器端。 它接受一个从远端客户端发出的创建一个新的TCP连接的接入请求,创建一个新的套接字,与该连接相应的套接字地址相关联。
     send()和recv(),或者write()和read(),或者recvfrom()和sendto(), 用于往/从远程套接字发送和接受数据。
     close() 用于系统释放分配给一个套接字的资源。 如果是TCP,连接会被中断。
     gethostbyname()和gethostbyaddr() 用于解析主机名和地址。
     select() 用于修整有如下情况的套接字列表: 准备读,准备写或者是有错误。
     poll() 用于检查套接字的状态。 套接字可以被测试,看是否可以写入、读取或是有错误。
     getsockopt() 用于查询指定的套接字一个特定的套接字选项的当前值。
     setsockopt() 用于为指定的套接字设定一个特定的套接字选项。
61、浮点数在计算中如何表示,如何对浮点数判等。
判断两个浮点数是否相等,不能简单的用 == 表示。要自己定义一个精度,当两个数的差的绝对值小于这个精度的时候,认为相等。
62、TCP、UDP和HTTP
63、使用C语言实现htonl(将long性转为网络字节码),不使用系统自带函数。
例如 int a = 0x12345678,b = htonl(a),那么就应该是0x78563412
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。 
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。 
以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图: 
栈底(高地址) 
---------- 
buf[3] 
buf[2] 
buf[1] 
buf[0] 
---------- 
栈顶(低地址) 

现在我们弄清了高低地址,接着我来弄清高/低字节,如果我们有一个32位无符号整型0x12345678(呵呵,恰好是把上面的那4个字节buf看成一个整型),那么高位是什么,低位又是什么呢?其实很简单。在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。 
高低地址和高低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义,并用图示说明两种字节序: 
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value: 
Big-Endian: 低地址存放高位,如下图: 
栈底(高地址) 
--------------- 
buf[3] (0x78) -- 低位 
buf[2] (0x56) 
buf[1] (0x34) 
buf[0] (0x12) -- 高位 
--------------- 
栈顶(低地址) 
Little-Endian: 低地址存放低位,如下图: 
栈底(高地址) 
--------------- 
buf[3] (0x12) -- 高位 
buf[2] (0x34) 
buf[1] (0x56) 
buf[0] (0x78) -- 低位 
--------------- 
栈顶(低地址) 

在现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。 
64、堆和栈的区别
65、请说出static和const关键字尽可能多的作用
static关键字至少有下列n个作用:

  (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

  (2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

  (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

  (4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

  (5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

  const关键字至少有下列n个作用:

  (1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;

  (2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;

  (3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;

  (4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;

  (5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:

               const classA operator*(const classA& a1,const classA& a2);

  operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:
               classA a, b, c;
               (a * b) = c; // 对a*b的结果赋值

  操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。

  剖析:

  惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。

  这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。
66、请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1
int checkCPU()
{
 {
  union w
  { 
   int a;
   char b;
  } c;
  c.a = 1;
  return (c.b == 1);
 }
}
剖析:
     嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 存放内容
0x4000 0x34
0x4001 0x12


  而在Big-endian模式CPU内存中的存放方式则为:


内存地址 存放内容
0x4000 0x12
0x4001 0x34


  32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:


内存地址 存放内容
0x4000 0x78
0x4001 0x56
0x4002 0x34
0x4003 0x12


  而在Big-endian模式CPU内存中的存放方式则为:


内存地址 存放内容
0x4000 0x12
0x4001 0x34
0x4002 0x56
0x4003 0x78



     联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。

抱歉!评论已关闭.