面试题4附加答案
来源:互联网 发布:问答系统源码 编辑:程序博客网 时间:2024/06/05 06:50
试卷四
一、填空选择题
1、请写出 float x 与“零值”比较的 if 语句 const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
解析:float是浮点数,不能用==,要用<和>配合一个接近0的数比较。
2、写出输出结果___________________________段错误________________________
char* s = “AAA”;
printf(“%s”, s);
s[0] = 'B';
printf(“%s”, s);
解析:因为printf是行缓冲,所以第一个没有回车符,所以没有进行输出AAA,段错误的原因,s只是一个指针,没有被分配空间,对没有分配的空间的操作;
3、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题):
#define SEC (365*24*60*60)UL
解析: 一个常数的定义,但是由于这个常数是一个无符号长整型;所以最后加一个UL
4、下面程序的输出结果是多少____250_______//0xfa_____
#include <stdio.h>
int main()
{
unsigned char a = 0xA5;
unsigned char b = ~ a >> 4 + 1;
printf(“b = %d\n”, b);
return 0;
}
解析:具体的失误的原因,主要对于这些的操作的优先级的顺序不知道。这里面,应该,先加,然后然后移位,最后才是取反;
5、(多选)在多重处理系统中,处理死锁的办法有两种:一是防止其发生;二是发生后进行处理。下面的方法属于防止其发生的是哪一个?________bc_____
A、破坏互斥条件
B、破坏不可剥夺条件
C、破坏循环等待条件
D、杀死某个激活死锁的进程
解析:所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。很显然,如果没有外力的作用,那麽死锁涉及到的各个进程都将永远处于封锁状态。
产生死锁的4个必要条件是:
互斥条件:即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。如打印机。
不可抢占条件:进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。
占有且申请条件:进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。
循环等待条件:存在一个进程等待序列{P1,P2,…,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,……,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。
根据产生死锁的4个必要条件,只要使其中之一不能成立,死锁就不会出现。
为此,可采用下列3种预防措施:
采用资源静态分配策略,破坏“部分分配”条件;
允许进程剥夺使用其他进程占有的资源,从而破坏“不可剥夺”条件;
采用资源有序分配法,破坏“环路”条件。
但注意一点:互斥条件无法被破坏。本题中A是无法做到的,B和C正确,D选项属于死锁事后处理操作,与题意不符合。
二、简答题
1、系统调用与库函数的区别?
Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思。面向的是硬件。而库函数调用则面向的是应用开发的,相当于应用程序的api,采用这样的方式有很多种原因,第一:双缓冲技术的实现。第二,可移植性。第三,底层调用本身的一些性能方面的缺陷。第四:让api也可以有了级别和专门的工作面向。
函数库调用
系统调用
在所有的ANSI C编译器版本中,C库函数是相同的
各个操作系统的系统调用是不同的
它调用函数库中的一段程序(或函数)
它调用系统内核的服务
与用户程序相联系
是操作系统的一个入口点
在用户地址空间执行
在内核地址空间执行
它的运行时间属于“用户时间”
它的运行时间属于“系统”时间
属于过程调用,调用开销较小
需要在用户空间和内核上下文环境间切换,开销较大
在C函数库libc中有大约300个函数
在UNIX中大约有90个系统调用
典型的C函数库调用:system fprintf malloc
典型的系统调用:chdir fork write brk;
2、sizeof与strlen的区别?
1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
2.sizeof是算符,strlen是函数。
3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾。
4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。
5.大部分编译程序 在编译的时候就把sizeof计算过了 是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因
6.strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。
7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。
8.当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸
9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,
3、关键字register的用法及注意事项?
答: 修饰经常被访问的变量,它所修饰的变量,请求编译器的尽可能的将变量保存在cpu的寄存器中。这样有助于减少访存的时间
有助于程序的效率。
它所修饰的变量不能用&地址,因为&这个是取的是内存空间的的地址,但是register 修饰的的变量保存在寄存器里面。
还有register只能修饰cpu能够接受的类型,例如cpu是不能进行浮点类型的计算。
register修饰的是局部变量不能修饰全局变量,因为只有这个进程知道这个变量的在哪里保存着,而其它的进程不知这个
变量保存的地方。
4、用联合体判断大小端,大端返回0,小端返回1
union w
{
int a;
char b;
} u;
int bigorlittle(void)
{
u.a = 1;
return (n.b == 1);
}
5、TCP是如何保证数据可靠传输?
(1)应用数据被分割成TCP认为的最合适发送的数据块;
(2)当TCP发出一个报文段后,就启动一个定时器,用来等待目的端确认收到这个报文段;若没能及时收到这个确认,TCP发送端将重新发送这个报文段(超时重传);
(3)TCP收到一个发自TCP连接的另一端的数据后就将发送一个确认,不过这个确认不是立即就发送,而是要推迟几分之一秒后才发送;
(4)TCP将保持它的首部和数据的检验和;(这是一个端到端的检验和,为了检验数据在传输过程中发生的错误;若检测到段的检验和有差错,TCP将丢弃和不确认收到此报文段并希望发端可以进行超时重传)
(5)由于TCP报文段是作为IP数据报来传输的,又因为IP数据报的到达可能会失序,所以TCP报文段的到达也可能会失序;因此,有必要的话TCP会对收到的数据进行重新排序后交给应用层;
(6)因为TCP报文段是作为IP数据报来传输的,并且IP数据报可能会发生重复,所以TCP的接收端必须丢弃掉重复的数据;
(7)TCP提供流量控制;(因为TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这一限制可以防止较快主机致使较慢主机的缓冲区溢出)
三、程序题
1、编程实现strstr。
char * my_strstr(const *str, char * dst)
{
int i =0;
char* temp1 =str;
char *temp2 =dst;
char * temp3;
if(dst ==NULL)
{
return NULL;
}
while ( (*temp1) != ‘\0’)
{
temp3= temp1;
temp2 = dest;
while(1)
{
if( (*temp3 ) != (*temp2))
{
break;
}
if((*temp2) == ‘\0’)
{
return temp1;
}
temp2++;
temp3++;
}
}
return NULL:
}
2、合并两个递增排序链表
struct node
{
int num;
struct node *next;
};
typedef struct node Node;
typedef Node * Link;
Link Merge(Link head1, Link head2)
{
Node * temp1 =head1;
Node *temp2 =head2;
Node *temp3 = NULL;
if(temp1 == NULL)
{
return temp2;
}
if(temp2 == NULL)
{
return temp1;
}
if(temp1->num> temp2->num)
{
temp3 = temp1;
temp1= temp2;
tmp2 =temp3;
}
while(temp1 != NULL)
{
if((temp1->num)< (temp2->num))
{s
temp3 = temp1->next ;
temp1= temp2;
temp2 = temp2->next;
temp1->next->next =temp3;
temp2= temp2->next;
if(temp2 == NULL )
{
break;
}
}
else
{
temp1 = temp1->next;
}
}
return temp1;
}
- 面试题4附加答案
- Linux面试题完整修订附加答案
- 2017面试题的总结——附加答案
- iOS面试题4(答案)
- 程序员经典面试题及答案4
- Python面试题集答案(4)
- Android面试题及答案4
- c#面试题----答案
- 面试题以及答案
- 面试题(无答案)
- 面试题及答案
- 面试题及其答案
- 面试题五答案
- 面试题六答案
- 面试题7答案
- 面试题8答案
- 面试题9答案
- 面试题10答案
- v4l2 ioctl 学习总结
- Excel获取Sheet表名
- ROS机器人Diego 1#制作(十二)SLAM导航的配置
- c++小知识点5.0
- SW4Stm32开发环境搭建
- 面试题4附加答案
- 彻底修改 Windows 系统用户名 完美实现修改管理员帐号
- 戏说春秋一三令五申
- 逻辑推理 - 归纳推理
- php笔记
- Eclipse启动tomcat无法访问的解决方法
- 用python做自动化测试--web 自动化测试(1)-Selenium 3.x使用系列问题集
- 关于字符串的逆序题目
- 145. Binary Tree Postorder Traversal 树后续遍历 flag方法和reverse方法