《笔试经典题-精品文档资料整理.doc》由会员分享,可在线阅读,更多相关《笔试经典题-精品文档资料整理.doc(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。#define SECONDS_PER_YEAR (365*24*60*60)UL2.写一个标准宏MIN,这个宏输入两个参数并返回较小的一个。#define MIN (A)=(B)?(A):(B)3.预处理器标识#error的目的是什么?#error 记号序列将使预处理器打印包含该记号序列的诊断信息。4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?While(1)5.用变量a给出下面的定义a)一个整型数(Aninteger)b)一个指向整型数的指针(Apointertoaninteger)c)一个
2、指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoanintege)rd)一个有10个整型数的数组(Anarrayof10integers)e)一个有10个指针的数组,该指针是指向一个整型数的。(Anarrayof10pointerstointegers)f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)h)一个
3、有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnaninteger)a) int a;b) int *a;c) int *a;d) int a10;e) int *a10;f) int (*a)10;g) int (*a)(int );h) int (*a10)(int );6.关键字static的作用是什么?答:1)在函数体内,被声明为静态的变量在函数内被调用的过程中维持值不变,这个局部变量存储域发生改变,从栈到data中,所以这个值
4、不变。(static局部变量只被初始化一次,下一次依据上一次结果值; 2)在模块内被声明的静态全局变量,能被模块内部声明之后的函数调用,但不能被模块外的函数调用。这是一个本地的变量。所以声明为静态的全局变量的作用域发生改变,限制了它的使用范围。3)在模块内的声明的静态函数,可以被模块内部的其他函数调用,但不可被模块外部的函数调用。也就是这个函数被限制在声明它的模块使用。对于可在原模块外部使用的函数,应该在一个头文件中说明,要使用这些函数的模块需包含这个头文件。7关键字const有什么含意?1)使用Const关键字的地方是为了说明这个参数为常量,是不应该被修改的。2)合理使用const 可以是编
5、译器自然的保护那些不希望被修改的参数,防止被无意的代码修改。3)通过给优化器一些有用的信息,使用关键字const也许是代码更加紧凑。题:1.有以下表达式: int a=248; b=4;int const c=21;const int *d=&a; int *const e=&b;int const *f const =&a; 请问下列表达式哪些会被编译器禁止?为什么? *c=32;d=&b;*d=43;e=34;e=&a;f=0x321f; *c 这是个什么东东,禁止 *d 说了是const, 禁止 e = &a 说了是const 禁止 const *f const =&a; 禁止 下面的声
6、明都是什么意思?1)constinta;2)intconsta;3)constint*a;4)int*consta;5)intconst*aconst;1) a是一个常整数;2) a是一个常整数;3) a是一个指向常整形的指针4) a是一个指向整型的常指针;5) a是一个指向常整型的常指针;8.关键字volatile有什么含意?并给出三个不同的例子。一个定义为volatile的变量就是说它可能会意想不到的改变(改变它的情况有很多,例如操作系统,硬件,线程),这样,编译器就不会去假设这个值,也就是说,当优化器读到这个值时就会小心翼翼的去重新读取这个变量的值,而不是使用保存在寄存器中的备份。(当使
7、用到用类型修饰符声明的变量时,系统总是从它所在的内存读取,既使系统刚从这里读取过)Volatile修饰符告诉编译程序不要对该变量所参与的操作进行优化。大多数计算机拥有一系列寄存器,其存取速度比计算机主存更快。好的编译程序能进行一种被称为“冗余装入和存储的删去”(redundant load and store removal)的优化,即编译程序会在程序中寻找并删去这样两类代码:一类是可以删去的从内存装入数据的指令,因为相应的数据已经被存放在寄存器中;另一种是可以删去的将数据存入内存的指令,因为相应的数据在再次被改变之前可以一直保留在寄存器中。例如:volatile i=10;int a=i;例
8、子:1) 并行设备的硬件寄存器。存储器映射的硬件寄存器通常加volatile例如状态寄存器。以为设备寄存器会在你的程序不知道或者不介入的时候发生改变,那是因为设备寄存器可以被外设硬件修改。相反,变量中的不会变。设备寄存器的内容是易失的,或者在不注意的时候被修改。当声明指向设备寄存器的指针时一定要用volatile它会告诉编译器不要对存储在这个地址的数据进行假设,编译器在优化这个变量时应该把它看作编译时未知的。#define IOPMOD (*(Volatile unsigned *)(SYSCFG + 0x5000)2) 一个中断服务程序中修改的供其他程序检测的变量。3) 多线程应用中被几个任
9、务共享的变量。1.一个变量可以既是const 还是volatile吗?解释为什么?可以,例如状态寄存器。它首先应该是volatile 因为它可以出乎意料的修改,而且应该是const,这个寄存器程序不应该去修改。2.一个指针可以说volatile的吗?可以,例如中断服务子程序中修改一个指向buffer的指针。3.下列代码有错误吗?Int square(volatile int *ptr)Return *ptr *ptr;答:由于ptr声明为volatile类型的所以编译器可能编译完的程序是:intsquare(volatileint*ptr)inta,b;a=*ptr;b=*ptr;return
10、a*b;则得出的结果可能不是想要的结果;正确的程序这样写:longsquare(volatileint*ptr)inta;a=*ptr;returna*a;9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。#define BIT3 (0x01 6)?(“6):(“= - EPSINON) & (x =”或“=”形式。如果写成if (x = 0.0),则判为错,得0分。试题4:为什么标准头文件都有类似以下的结构? #ifndef _INCvxWorksh#define _INCvx
11、Worksh #ifdef _cplusplusextern C #endif /*.*/ #ifdef _cplusplus#endif #endif /* _INCvxWorksh */解答:头文件中的编译宏#ifndef_INCvxWorksh#define_INCvxWorksh#endif 的作用是防止被重复引用。作为一种面向对象的语言,C+支持函数重载,而过程式语言C则不支持。函数被C+编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo(int x, int y);该函数被C编译器编译后在symbol库中的名字为_foo,而C+编译器则会产
12、生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C+就是考这种机制来实现函数重载的。为了实现C和C+的混合编程,C+提供了C连接交换指定符号extern C来解决名字匹配问题,函数声明前加上extern C后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C+的函数了。试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1解答:int checkCPU()union w int a;char b; c;c.a = 1;return (c.b = 1
13、);剖析:嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:内存地址存放内容0x40000x340x40010x12而在Big-endian模式CPU内存中的存放方式则为:内存地址存放内容0x40000x120x40010x3432bit宽的数0x12345678在Little-endian模式
14、CPU内存中的存放方式(假设从地址0x4000开始存放)为:内存地址存放内容0x40000x780x40010x560x40020x340x40030x12而在Big-endian模式CPU内存中的存放方式则为:内存地址存放内容0x40000x120x40010x340x40020x560x40030x78联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。试题2:写一个函数返回1+2+3+n的值(假定结果不会超过长整型变量的
15、范围) 解答:int Sum( int n ) return ( (long)1 + n) * n / 2;/或return (1l + n) * n / 2;剖析:对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return ( 1 l + n ) * n / 2相比! int Sum( int n )long sum = 0;for( int i=1; i0.000001|x-0.000001)X = 0If(x-0.000001)24)internet采用哪种网络协议,该协议的主要层次是什么?Tcp/IP
16、 主要层次有应用层 传输层 网络层 数据链路层 物理层ISO的七层模型是什么?应用层 表示层 会话层 传输层 网络层 物理链路层 物理层Tcp udp属于运输层Tcp服务提供了数据流传输,可靠性,有效流控制,全双工操作和多路复用技术Udp不提供可靠性,流控制以及错误恢复功能 udp头包含少,负载消耗小。优缺点:Tcp提供可靠的传输服务,有流量控制。缺点是包头大,冗余性不好。Udp不提供稳定的服务 但包头小 开销小。Internet物理地址和ip地址转换采用什么协议?ARP(地址解析协议)IP地址的编码分为那两部分?网络号 和主机号 不过要与子网掩码与之后才能区分哪是网络号那是主机号。2.用户输
17、入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。 循环链表,用取余操作做3.不能做switch()的参数类型是: switch的参数不能为实型。进程和线程的区别是什么?进程是程序的一次执行线程是进程内的一个执行单元,也是进程内的可调度实体。与进程的区别:调度:线程是可调度和分配的基本单元,进程是拥有资源的基本单位。并发性:不同进程和同一个进程中的多个线程都可以并发。拥有资源:进程是拥有资源的独立单位,而线程不拥有资源,但它可以访问属于进程的资源。系统开销:由于创建进程和撤销进程 系统都要为之分配和回收资源,所以系统的开销明显大于线程创建和撤销时的开销。7谈谈
18、COM的线程模型。然后讨论进程内/外组件的差别。1网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别?1) 进程:子进程是父进程的复制,它获得父进程数据空间,堆 栈的复制品。2) 线程:相对于进程而言,线程更接近于一个执行体的概念,它可以与同进程的其他线程同享进程资源,但同时拥有自己的栈空间,寄存器,指针(独立的执行序列)。3) 两者都可以提高程序的并发度,提高程序的运行效率和响应。4) 线程和进程各有优缺点,线程开销少,但不利于资源管理和保护。而进程恰恰相反,开销大,但对资源有独立掌控权,可更好地管理。2.列举几种进程的同步机制1)原子操作2)信号量机制3)自旋锁 4)管程,
19、会合,分布式系统3 进程间的通讯的途径共享存储系统消息传递系统管道:以文件系统为基础11.进程死锁的原因 资源竞争及进程推进顺序非法 12.死锁的4个必要条件 互斥、请求保持、不可剥夺、环路13.死锁的处理 鸵鸟策略、预防策略、避免策略、检测与解除死锁15. 操作系统中进程调度策略有哪几种? FCFS(先来先服务),优先级,时间片轮转,多级反馈10.数组和链表的区别 数组:数据顺序存储,固定大小 连表:数据可以随机存储,大小可动态改变面试题: 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈? 进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的
20、时候操作系统就帮你创建了一个主线程。 每个线程有自己的堆栈。 DLL中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈? 以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃用宏定义写出swap(x,y)#
21、define swap(x,y) (x=x+y;y=x-y;x=x-y)char * const p; char const * p const char *p 上述三个有什么区别? char * const p; /常量指针,p的值不可以修改 char const * p;/指向常量的指针,指向的常量值不可以改 const char *p; /和char const *p char str1 = abc; char str2 = abc; const char str3 = abc; const char str4 = abc; const char *str5 = abc; const c
22、har *str6 = abc; char *str7 = abc; char *str8 = abc; cout ( str1 = str2 ) endl; cout ( str3 = str4 ) endl; cout ( str5 = str6 ) endl; cout ( str7 = str8 ) endl; 结果是:0 0 1 1 解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间; 而str5,str6,str7,str8是指针,它们指向相同的常量区域。12. 以下代码中的两个sizeof用法有问题吗?C易 void UpperCase( char st
23、r ) / 将 str 中的小写字母转换成大写字母 for( size_t i=0; isizeof(str)/sizeof(str0); +i ) if( a=stri & stri=z ) stri -= (a-A ); char str = aBcDe; cout str字符长度为: sizeof(str)/sizeof(str0) endl; UpperCase( str ); cout str endl; 答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数
24、内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。main() int a5=1,2,3,4,5; int *ptr=(int *)(&a+1); printf(%d,%d,*(a+1),*(ptr-1); 输出:2,5 *(a+1)就是a1,*(ptr-1)就是a4,执行结果是2,5 &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) int *ptr=(int *)(&a+1); 则ptr实际是&(a5),也就是a+5 原因如下: &a是数组指针,其类
25、型为 int (*)5; 而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a5 但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a0的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a1,&a+1是下一个对象的地址,即a5. 互斥量Void pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);Int