程序员笔试题收集汇总(⼀)
1.下列 C 代码中,不属于未定义⾏为的有_
A: Int i=0;i=(i++);
B: char *p=”hello”;p[1]=’E’;
C: char *p=”hello”;char ch=*p++;
D: int i=0;printf(“%d%d\n”,i++,i–);
E: 都是未定义⾏为
F: 都不是未定义⾏为
正确答案: C
解析:C语⾔中的未定义⾏为(Undefined Behavior)是指C语⾔标准未做规定的⾏为。同时,标准也从没要求编译器判断未定义⾏为,所以这些⾏为有编译器⾃⾏处理,在不同的编译器可能会产⽣不同的结果,⼜或者如果程序调⽤未定义的⾏为,可能会成功编译,甚⾄⼀开始运⾏时没有错误,只会在另⼀个
系统上,甚⾄是在另⼀个⽇期运⾏失败。当⼀个未定义⾏为的实例发⽣时,正如语⾔标准所说,“什么事情都可能发⽣”,也许什么都没有发⽣。
所以,避免未定义⾏为,是个明智的决定。本⽂将介绍⼏种未定义⾏为,同时欢迎读者纠错和补充。
1.同⼀运算符中多个操作数的计算顺序(&&、||、?和,运算符除外)
例如:x = f()+g(); //错误
f()和g()谁先计算由编译器决定,如果函数f或g改变了另⼀个函数所使⽤变量的值,那么x的结果可能依赖于这两个函数的计算顺序。
参考: 《C程序设计语⾔(第2版)》 P43
2.函数各参数的求值顺序
例如: printf(“%d,%d\n”,++n,power(2,n)); //错误
在不同的编译器可能产⽣不同的结果,这取决于n的⾃增运算和power调⽤谁在前谁在后。
需要注意的是,不要和逗号表达式弄混,都好表达式可以参考这篇⽂章:c语⾔中逗号运算符和逗号表
达式
参考: 《C程序设计语⾔(第2版)》 P43
3.通过指针直接修改 const 常量的值
直接通过赋值修改const变量的值,编译器会报错,但通过指针修改则不会
2. 6⽀笔,其笔⾝和笔帽颜⾊相同:但6⽀笔颜⾊各不相同,求全部笔⾝都戴错笔帽的可能性有多少种?
A:265
B: 266
C:267
D:268
答案:A
解析:⽹上摘抄(排错公式)
第⼀步,把第n个元素放在⼀个位置,⽐如位置k,⼀共有n-1种⽅法;
第⼆步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种⽅法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种⽅法(相当与K于原N的位置是⼀对,当时由于K不放在N的位置上,形成类似与“排错,不能构成匹配的语⾔”,则有n-1个元素);
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
3. 假定变量I,f,d数据类型分别为int,float和double(int⽤补码表⽰,float和double分别⽤IEEE754单精度和双精度浮 点数据格式表⽰),已知i=785,f=1.5678e^3,d=1.5e^100若在32位机器 中执⾏下列关系表达式,则结果为真是()
(I)i==(int)(float)I
(II)f==(float)(int)f
(III)f==(float)(double) f
(IV)(d+f)-d==f
A:仅I和II
B:仅I和III
C:仅II和III
D:仅III和IV
答案:B
(I)i==(int)(float)I 由于i(int)经过强制类型转换从int->float->int和左边相同 正确
(II)f==(float)(int)f 由于f(float)经过强制类型转换 从float->int,虽然int也强制类型转换了但是⼩数点已经去掉,故精度丢失,和左边不⼀样,错误
(III)f==(float)(double) f 由于f(float)经过强制类型转换 从float->double->float和左边相同 正确
(IV)(d+f)-d==f 左边为了尽量保证精度不丢失,⼀般会把低转化为⾼精度从float->double 和右边float不同 错误
4. 每份考卷都有⼀个8位⼆进制序列号。当且仅当⼀个序列号含有偶数个1时,它才是有效的。例如,00000000、01010011都是有效的序列号,⽽11111110不是。那么,有效的序列号共有() 个
A:127
B:128
C:255
D:256
答案:B
总共有2^8=256个序列,其中要么含有偶数个1,要么奇数个,所以对半分为128个。
(可理解为⼆项分布 (1 +(-1))^8, 由于 (1-1)^8=0,则 结果中有效的⽆效的对半)
5. 求输出结果
int a[2][2][3]= { {{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}}};
int *ptr=(int *)(&a+1);
printf(“%d %d”, *(int*)(a+1), *(ptr-1));
1
2
3
A:7 12
B:1 6
C:1 3
D:7 9
正确答案: A
6. 有哪⼏种情况只能⽤intialization list ⽽不能⽤assignment?
A:当类中含有const成员变量
B:基类⽆默认构造函数时,有参的构造函数都需要初始化表。
C:当类中含有reference成员变量
D:当类中含有static成员变量
正确答案: A B C
因为const对象以及引⽤只能初始化⽽不能赋值,所以只能使⽤成员初始化列表。
对于⾮内置类型,在进⼊函数体之前,如果没有提供显式初始化,会调⽤默认构造函数进⾏初始化。若没有默认构造函数,则编译器尝试调⽤默认构造函数将会失败,所以如果没有默认构造函数,则必须在初始化列表中显⽰的调⽤构造函数。
static 成员在执⾏构造函数前就已经构造好了,即使不存在类对象,也可以被使⽤,不需要初始化列表
7. 下列TCP连接建⽴过程描述正确的是:
A:服务端收到客户端的SYN包后等待2*ml时间后就会进⼊SYN_SENT状态
B:服务端收到客户端的ACK包后会进⼊SYN_RCVD状态
C:当客户端处于ESTABLISHED状态时,服务端可能仍然处于SYN_RCVD状态
D:服务端未收到客户端确认包,等待2*ml时间后会直接关闭连接
正确答案: C
关于D,如果服务器处于SYN_Recv状态,发送了同步+确认包后,没有收到客户端的确认包,则⼀般会重试,重新发送同步+确认包后,并等待⼀段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,⼀般来说这个时间是分钟的数量级(⼤约为30秒-2分钟);⼀个⽤户出现异常导致服务器的⼀个线程等待1分钟并不是什么很⼤的问题,但如果有⼀个恶意的攻击者⼤量模拟这种情况,服务器端将为了维护⼀个⾮常⼤的半连接列表⽽消耗⾮常多的资源—-数以万计的半连接,即使是简单的保存并遍历也会消耗⾮常多的CPU时间和内存,何况还要不断对这个列表中的IP进⾏SYN+ACK的重试。此时从正常客户的⾓度看来,服务器失去响应,这种情况我们称做:服务器端受到了SYN Flood攻击(SYN洪⽔攻击)
8. 以下对CSMA/CD描述正确的是?
A:在数据发送前对⽹络是否空闲进⾏检测
B:在数据发送时对⽹络是否空闲进⾏检测
C:在数据发送时对发送数据进⾏冲突检测
D:发⽣碰撞后MAC地址⼩的主机拥有发送优先权
答案:AC
CSMA/CD协议即带冲突检测的载波监听多路访问协议。
A,发送前空闲检测,只有信道空闲才发送数据
B,发送时当前信号占据信道,信道必定不为空闲,检测空闲没意义
C,发送过程中冲突检测,如果发⽣冲突,⽴即停⽌发送,随机避让。
D,冲突发送后,两个发送端都随机避让⼀段时间,避让的时间是随机的,优先级相等,没有哪个优先权⾼的说法。
笔试题
9.以下哪些线程同步锁可以为递归
1.信号量
2.读写锁
3.互斥量
4.事件
5.临界区(Critical Section)
A: 1,3,4,5
B:5
C:3,5
D:1,3,5
正确答案: C
进程/线程同步⽅法
常见的进程/线程同步⽅法有互斥锁(或称互斥量Mutex)、读写锁(rdlock)、条件变量(cond)、信号量(Semophore)等。
在windows系统中,临界区(Critical Section)和事件对象(Event)也是常⽤的同步⽅法。
递归锁/⾮递归锁
Mutex可以分为递归锁(recursive mutex)和⾮递归锁(non-recursive mutex)。 递归锁也叫可重⼊锁(reentrant mutex),⾮递归锁也叫不可重⼊锁(non-reentrant mutex)。
⼆者唯⼀的区别是:
同⼀个线程可以多次获取同⼀个递归锁,不会产⽣死锁。
如果⼀个线程多次获取同⼀个⾮递归锁,则会产⽣死锁。
Windows下的Mutex和Critical Section是可递归的。
Linux下的pthread_mutex_t锁是默认是⾮递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。
10. A、B、C、D四⼈应聘⼀个程序员职位,此职务的要求条件是:Java熟练;懂数据库开发;会Web开发;有C++经验。谁满⾜的条件最多,谁就被雇⽤。(1)把上⾯四个要求条件两两组合,每个组合都恰有⼀⼈满⾜。同时已知(2)A和Bjava熟练(3)B和C会
Web(4)C和D懂数据库(5)D有C++经验那么,被雇⽤的是__。
A:A
B:B
C:C
D:D
E:四⼈机会均等
F:以上均错
解析:经过推测为(s为数据库)
A B C D
java java X X
X web web X
S X S S
X C X C
所以为B
11. 下⾯程序的结果是:
class Supper{
public Integer get()
{
System.out.println("s");
return 4;
}
}
public class test extends Supper{
public Long get()
{
System.out.println("b");
return new Long("5");
}
public static void main(String args[])    {
Supper s=new Supper();
test test=new test();
<();
<();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
答案:编译错误
扩展:
11. 1下⾯程序的结果是: