21、以下说法不正确的是()
A、进程调度中"可抢占"和"非抢占"两种方式,后者引起系统的开销更大
B、每个进程都有自己的文件描述符表,所有进程共享同一打开文件表和v-node表
C、基本的存储技术包括RAM,ROM,磁盘以及SSD,其中访问速度最慢的是磁盘,CPU的高速缓存一般是由RAM组成的
D、多个进程竞争源出现了循环等待可能造成系统死锁
21、A
抢占式会引起系统的开销更大。
可抢占式调度是严格保证任何时刻,让具有最高优先数(权)的进程占有处理机运行,因此增加了处理机调度的时机,引起为退出处理机的进程保留现场,为占有处理机的进程恢复现场等时间(和空间)开销增大。
22、对于Linux说法,下列说法正确的是()
A、线性访问内存非法时,当前线程会进入信号处理函数
B、用mv命令移动文件时,文件的修改时间会发生变化
C、ulimit -c设置的是函数调用栈的大小
D、malloc函数是应用程序向操作系统申请内存的接口
22、A
B:不会变化
C:ulimit用于shell启动进程所占用的资源.-c size:设置core文件的最大值.单位:blocks
D:malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
23、X86体系结构在保护模式下中有三种地址,请问一下那种说法是正确的?
A、虚拟地址先经过分段机制映射到线性地址,然后线性地址通过分页机制映射到物理地址
B、线性地址先经过分段机制映射到虚拟地址,然后虚拟地址通过分页机制映射到物理地址
C、虚拟地址先经过分页机制映射到线性地址,然后线性地址通过分段机制映射到物理地址
D、线性地址先经过分页机制映射到虚拟地址,然后虚拟地址通过分段机制映射到物理地址
23、A
分段机制就是把虚拟地址空间中的虚拟内存组织成一些长度可变的称为段的内存块单元
分页机制把线性地址空间和物理地址空间分别划分为大小相同的块。这样的块称之为页。通过在线性地址空间的页与物理地址空间的页之间建立的映射,分页机制实现线性地址到物理地址的转换
24、当需要对文件进行随机存取时,下列哪一种文件物理结构不适用于上述应用场景?
A、顺序文件
B、索引文件
C、链接文件
D、Hash文件
24、C
链式存储只能顺序访问,不能随机访问。如果要随机访问的话只能顺序查找,效率低下
25、
#include<iostream>
using namespace std;
class MyClass
{
public:
MyClass(int i = 0)
{
cout << i;
}
MyClass(const MyClass &x)
{
cout << 2;
}
MyClass &operator=(const MyClass &x)
{
cout << 3;
return *this;
}
~MyClass()
{
cout << 4;
}
};
int main()
{
MyClass obj1(1), obj2(2);
MyClass obj3 = obj1;
return 0;
}
运行时的输出结果是()
A、11214444
B、11314444
C、122444
D、123444
25、C
解释:
首先程序中存在三个MyClass对象。
前两个对象构造时分别输出1,2
第三个对象是这样构造的MyClass obj3 = obj1;这里会调用拷贝构造函数,输出2
然后三个对象依次析构,输出444
所以最终输出122444
26、在一个64位的操作系统中定义如下结构体:
struct st_task
{
uint16_t id;
uint32_t value;
uint64_t timestamp;
};
同时定义fool函数如下:
void fool()
{
st_task task = {};
uint64_t a = 0x00010001;
memcpy(&task, &a, sizeof(uint64_t));
printf("%11u,%11u,%11u", task.id, task.value, task.timestamp);
}
上述fool()程序的执行结果为()
A、1,0,0
B、1,1,0
C、0,1,1
D、0,0,1
26、A
根据4字节对齐原则,id占用4字节,value占用4字节,timestamp占用8字节
a高位补0则为 0x 0000 0000 0001 0001
复制给结构体时:
低位4个字节复制到id --> id为1
高为4个字节复制到value --> value为0
timestamp不改变
如果8字节对齐,那么就更容易了,直接a覆盖到id上,答案还是A
27、下面代码会输出什么()
int main(int argc, char **argv)
{
int a[4] = {1, 2, 3, 4};
int *ptr = (int *)(&a + 1);
printf("%d", *(ptr - 1));
}
A、1
B、2
C、3
D、4
27、D
&a是数组指针,其类型为int(*)[4];
而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同,a是长度为4的int数组指针,所以要加5*sizeof(int),所以ptr实际是a[4],但是ptr与(&a+1)类型是不一样的,这点非常重要,所以ptr-1只会减去sizeof(int*),a,&a的地址是一样的,但意思就不一样了,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[4]
28、
int fun(int a)
{
a = (1 << 5) - 1;
return a;
}
Fun(21)结果是()
A、10
B、8
C、5
D、31
28、D
1<<5,这里1左移5位相当于1乘以2的5次方,也就是32
29、下面哪一个是sort的template的正确写法
A、void sort(class A first,class A last,class B pred)
B、void template(class A,class B)sort(A first,A last,B pred)
C、template<class A><class B> void sort(A first,A last,B pred)
D、template<class A,class B> void sort(A first,A last,B pred)
29、D
模板函数格式是先声明模板类型,然后才能使用
格式是 template<class T1, class T2, ...> 返回值 函数名(参数列表)
30、在c++中,
const int i = 0;
int *j = (int *) &i;
*j = 1;
printf("%d,%d", i, *j)
输出是多少?
A、0,1
B、1,1
C、1,0
D、0,0
30、A
const修饰的常量值具有不可变性,c++编译器通常会对该变量做优化处理,在编译时变量i的值为已知的,编译器直接将printf输出的变量i替换为0。尽管如此,编译器仍然会为变量i分配存储空间,通过修改内存的hack方式将变量i在内存中的值修改后并不影响printf的输出。
如果将i更改为volatile const int类型的,编译器就不会对变量i做优化,printf输出的结果就为1。
31、如下代码输出结果是什么?
#include<stdio.h>
char *myString()
{
char buffer[6] = {0};
char *s = "Hello World!";
for (int i = 0; i < sizeof(buffer) - 1; i++)
{
buffer[i] = *(s + i);
}
return buffer;
}
int main(int argc, char **argv)
{
printf("%s\n", myString());
return 0;
}
A、Hello
B、Hello World!
C、Well
D、以上全部不正确
31、D
函数char *myString()中没有使用new或者malloc分配内存,所有buffer数组的内存区域在栈区
随着char *myString()的结束,栈区内存释放,字符数组也就不存在了,所以会产生野指针,输出结果未知
32、不能把字符串"HELLO!"赋给数组b的语句是()
A、char b[10]={'H','E','L','L','O','!','\0'};
B、char b[10];b="HELLO!";
C、char b[10]:strcpy(b,"HELLO!");
D、char b[10]="HELLO!";
32、B
选项B并没有将数组b赋值为 hello! 因子b是数组的首地址,b="HELLO!";是改变了这个指针的指向,是错误的。
33、
struct Date
{
char a;
int b;
int64_t c;
char d;
};
Date data[2][10];
在32位系统上,如果Data的地址是x,那么data[1][5].c的地址是()
A、X+195
B、X+365
C、X+368
D、X+215
33、C
结构体成员地址对齐
a b c d
1+(3)+4+8+1+(7)= 24,()内表示为了满足对齐填充的大小。
&data[1][5].c = x+10*24+5*25+1+(3)+4=368。
34、如何定义一个int类型的指针数组,数组元素个数为10个:
A、int a[10];
B、int (*a)[10];
C、int *a[10];
D、int (*a[10])(int);
34、C
“[]”的优先级比“*”要高。
B中,“()”的优先级比“[]”高,“*”号和a构成一个指针的定义,指针变量名为a,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚a 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针
C中,a先与“[]”结合,构成一个数组的定义,数组名为a,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10 个指向int 类型数据的指针,即指针数组。
35、将一颗有100个结点的完全二叉树从根这一层开始,进行广度遍历编号,那么编号最小的叶节点的编号是()
A、49
B、50
C、51
D、52
35、C
100个结点的完全二叉树,度为0的结点比度为2的结点多一个。所以度为2的结点有49个,度为1的结点有1个,度为0的结点有50个
二叉树前k层最多有2^k-1个结点。所以100个结点二叉树高度为7,如果按照题目中深度遍历,编号最小的叶子结点为7,所以题目说错了
按照广度遍历编号,有50个非叶子结点,所以最小的叶子结点编号为51
36、解析XML时,需要校验节点是否闭合,如必须有与之对应,用()数据结构实现比较好
A、链表
B、树
C、队列
D、栈
36、D
栈是解决封闭对应问题的有效方法。
比如在解析XML中,遇到一个<demo>标签(左标签)就入栈,遇到其子标签的左标签(如<subdemo>)同样入栈。遇到右标签(如</subdemo>或</demo>)就校验栈顶标签是否与该右标签对应,能对应就出栈,不能对应则说明标签不对称,是无效的XML文件
37、快速排序算法在序列已经有序的情况下的复杂度为()
A、O(nlogn)
B、O(n^2)
C、O(n)
D、O(n^2 logn)
37、B
快排在完全无序的情况下效果最好,时间复杂度为O(nlogn),在有序情况下效果最差,时间复杂度为O(n^2)
38、无向图G=(V E),其中V={a,b,c,d,e,f},E={<a,b>,<a,e>,<a,c>,<b,e>,<c,f>,<f,d>},<e,d>,对该图进行深度优先排序,得到的顶点序列正确的是()
A、a,b,e,c,d,f
B、a,c,f,e,b,d
C、a,e,b,c,f,d
D、a,e,d,f,c,b
38、D
如果有<e,d>这条边就选择d,否则选c
二、解答题
39、在写一个函数,根据两文件的绝对路径算出相对路径。如 a="/qihoo/app/a/b/c/d/new.c",b="/qihoo/app/1/2/test.c',那么b相对于a的相对路径是"../../../../1/2/test.c"
39、
public class PathCal {
public static void main(String[] args) throws Exception {
String pathA = "/qihoo/app/a/b/c/d/new.c";
String pathB = "/qihoo/app/1/2/test.c";
System.out.println(pathRelative(pathB,pathA,""));
}
/**
* pathA相对于pathB的相对路径 递归算法:
*/
public static String pathRelative(String pathA,String pathB, String tempPath) {
if (pathA.startsWith(pathB))
return pathA.replaceFirst(pathB+"/",tempPath.substring(0,tempPath.length()-3));
else
return pathRelative(pathA, pathB.substring(0, pathB.lastIndexOf("/")), "../" + tempPath);
}
}