2.引用与指针有什么区别?1)引用必须被初始化,指针不必。2)引用初始化以后不能被改变,指针可以改变所指的对象。3)不存在指向空值的引用,但是存在指向空值的指针。
4.全局变量和局部变量在内存中是否有区别?如果有,是什么区别?全局变量储存在静态数据库,局部变量在堆栈。
5.什么是平衡二叉树?左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于1。
6.堆栈溢出一般是由什么原因导致的?没有回收垃圾资源。
9.写出floatx与“零值”比较的if语句。if(x>0.000001&&x<-0.000001)
10.Internet采用哪种网络协议?该协议的主要层次结构?Tcp/Ip协议主要层次结构为:应用层/传输层/网络层/数据链路层/物理层。
11.Internet物理地址和IP地址转换采用什么协议?ARP(AddressResolutionProtocol)(地址解析協議)
12.IP地址的编码分为哪俩部分?IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。
13.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。循环链表,用取余操作做
14.不能做switch()的参数类型是:switch的参数不能为实型。
1.写出判断ABCD四个表达式的是否正确,若正确,写出经过表达式中a的值(3分)inta=4;(A)a+=(a++);(B)a+=(++a);(C)(a++)+=a;(D)(++a)+=(a++);a=答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a)+=a;改后答案依次为9,10,10,11
4.回答下面的问题(6分)(1).VoidGetMemory(char**p,intnum){*p=(char*)malloc(num);}voidTest(void){char*str=NULL;GetMemory(&str,100);strcpy(str,"hello");printf(str);}请问运行Test函数会有什么样的结果?答:输出“hello”(2).voidTest(void){char*str=(char*)malloc(100);strcpy(str,“hello”);free(str);if(str!=NULL){strcpy(str,“world”);printf(str);}}请问运行Test函数会有什么样的结果?答:输出“world”(3).char*GetMemory(void){charp[]="helloworld";returnp;}voidTest(void){char*str=NULL;str=GetMemory();printf(str);}请问运行Test函数会有什么样的结果?答:无效的指针,输出不确定
5.编写strcat函数(6分)已知strcat函数的原型是char*strcat(char*strDest,constchar*strSrc);其中strDest是目的字符串,strSrc是源字符串。(1)不调用C++/C的字符串库函数,请编写函数strcat答:VC源码:char*__cdeclstrcat(char*dst,constchar*src){char*cp=dst;while(*cp)cp++;/*findendofdst*/while(*cp++=*src++);/*Copysrctoendofdst*/return(dst);/*returndst*/}(2)strcat能把strSrc的内容连接到strDest,为什么还要char*类型的返回值?答:方便赋值给其他变量
6.MFC中CString是类型安全类么?答:不是,其它数据类型转换到CString可以使用CString的成员函数Format来转换
7.C++中为什么用模板类。答:(1)可用来创建动态增长和减小的数据结构(2)它是类型无关的,因此具有很高的可复用性。(3)它在编译时而不是运行时检查数据类型,保证了类型安全(4)它是平台无关的,可移植性(5)可用于基本数据类型
8.CSingleLock是干什么的。答:同步多个线程对一个数据类的同时访问
9.NEWTEXTMETRIC是什么。答:物理字体结构,用来设置字体的高宽大小
10.程序什么时候应该使用线程,什么时候单线程效率高。答:1.耗时的操作使用线程,提高应用程序响应2.并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求。3.多CPU系统中,使用线程提高CPU利用率4.改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。其他情况都使用单线程。
11.Windows是内核级线程么。答:见下一题
12.Linux有内核级线程么。答:线程通常被定义为一个进程中代码的不同执行路线。从实现方式上划分,线程有两种类型:“用户级线程”和“内核级线程”。用户线程指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。这种线程甚至在象DOS这样的操作系统中也可实现,但线程的调度需要用户程序完成,这有些类似Windows3.x的协作式多任务。另外一种则需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部需求进行创建和撤销,这两种模型各有其好处和缺点。用户线程不需要额外的内核开支,并且用户态线程的实现方式可以被定制或修改以适应特殊应用的要求,但是当一个线程因I/O而处于等待状态时,整个进程就会被调度程序切换为等待状态,其他线程得不到运行的机会;而内核线程则没有各个限制,有利于发挥多处理器的并发优势,但却占用了更多的系统开支。WindowsNT和OS/2支持内核线程。Linux支持内核级的多线程
13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中?答:栈:存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理堆:程序运行时动态申请,new和malloc申请的内存就在堆上
14.使用线程是如何防止出现大的波峰。答:意思是如何防止同时产生大量的线程,方法是使用线程池,线程池具有可以同时提高调度效率和限制资源使用的好处,线程池中的线程达到最大数时,其他线程就会排队等候。
15函数模板与类模板有什么区别?答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定。
16一般数据库若出现日志满了,会出现什么情况,是否还能使用?答:只能执行查询等读操作,不能执行更改,备份等写操作,原因是任何写操作都要记录日志。也就是说基本上处于不能使用的状态。
18如果数据库满了会出现什么情况,是否还能使用?答:见16
19关于内存对齐的问题以及sizof()的输出答:编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
20inti=10,j=10,k=3;k*=i+j;k最后的值是?答:60,此题考察优先级,实际写成:k*=(i+j);,赋值运算符优先级最低
21.对数据库的一张表进行操作,同时要对另一张表进行操作,如何实现答:将操作多个表的操作放入到事务中进行处理
22.TCP/IP建立连接的过程(3-wayshake)答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
23.ICMP是什么协议,处于哪一层答:Internet控制报文协议,处于网络层(IP层)
24.触发器怎么工作的答:触发器主要是通过事件进行触发而被执行的,当对某一表进行诸如UPDATE、INSERT、DELETE这些操作时,数据库就会自动执行触发器所定义的SQL语句,从而确保对数据的处理必须符合由这些SQL语句所定义的规则。
25.winsock建立连接的主要实现步骤答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesocket()关闭套接字。
26.动态连接库的两种方式答:调用一个DLL中的函数有两种方法:1.载入时动态链接(load-timedynamiclinking),模块非常明确调用某个导出函数,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向系统提供了载入DLL时所需的信息及DLL函数定位。2.运行时动态链接(run-timedynamiclinking),运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了。
27.IP组播有那些好处答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧消耗和网络拥挤问题。组播是一种允许一个或多个发送者(组播源)发送单一的数据包到多个接收者(一次的,同时的)的网络技术。组播可以大大的节省网络带宽,因为无论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。所以说组播技术的核心就是针对如何节约网络资源的前提下保证服务质量。
发布之前先申明两点:1所有资料来自网络(主要是CSDN),本人只是收集和转发。2所有问题解答(尤其是代码)只是参考,不保证正确。
先发基本问题,再发编程问题..........
想成为嵌入式程序员应知道的0x10个基本问题:预处理器(Preprocessor)
2.写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。#defineMIN(A,B)((A)<=(B)(A):(B))这个测试是为下面的目的而设的:1)标识#define在宏中应用的基本知识。这是很重要的。因为在嵌入(inline)操作符变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。3)懂得在宏中小心地把参数用括号括起来4)我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?least=MIN(*p++,b);
3.预处理器标识#error的目的是什么?如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。
死循环(Infiniteloops)
4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?这个问题用几个解决方案。我首选的方案是:
while(1){
}
一些程序员更喜欢如下方案:
for(;;){
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:"我被教着这样做,但从没有想到过为什么。"这会给我留下一个坏印象。
第三个方案是用gotoLoop:...gotoLoop;应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。
5.用变量a给出下面的定义a)一个整型数(Aninteger)b)一个指向整型数的指针(Apointertoaninteger)c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoanintege)rd)一个有10个整型数的数组(Anarrayof10integers)e)一个有10个指针的数组,该指针是指向一个整型数的。(Anarrayof10pointerstointegers)f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnaninteger)
答案是:a)inta;//Anintegerb)int*a;//Apointertoanintegerc)int**a;//Apointertoapointertoanintegerd)inta[10];//Anarrayof10integerse)int*a[10];//Anarrayof10pointerstointegersf)int(*a)[10];//Apointertoanarrayof10integersg)int(*a)(int);//Apointertoafunctionathattakesanintegerargumentandreturnsanintegerh)int(*a[10])(int);//Anarrayof10pointerstofunctionsthattakeanintegerargumentandreturnaninteger
Static
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
Const
constinta;intconsta;constint*a;int*consta;intconst*aconst;
Volatile
8.关键字volatile有什么含意并给出三个不同的例子。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:1)并行设备的硬件寄存器(如:状态寄存器)2)一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)3)多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。1)一个参数既可以是const还可以是volatile吗?解释为什么。2);一个指针可以是volatile吗?解释为什么。3);下面的函数有什么错误:
intsquare(volatileint*ptr){return*ptr**ptr;}
下面是答案:1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。2);是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。3)这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
intsquare(volatileint*ptr){inta,b;a=*ptr;b=*ptr;returna*b;}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
longsquare(volatileint*ptr){inta;a=*ptr;returna*a;}
位操作(Bitmanipulation)
9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。对这个问题有三种基本的反应1)不知道如何下手。该被面者从没做过任何嵌入式系统的工作。2)用bitfields。Bitfields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bitfields因此完全对我无用,因为我的编译器用其它的方式来实现bitfields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。3)用#defines和bitmasks操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
#defineBIT3(0x1<<3)staticinta;
voidset_bit3(void){a|=BIT3;}voidclear_bit3(void){a&=~BIT3;}
一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
访问固定的内存位置(Accessingfixedmemorylocations)
10.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:int*ptr;ptr=(int*)0x67a9;*ptr=0xaa55;
Amoreobscureapproachis:一个较晦涩的方法是:
*(int*const)(0x67a9)=0xaa55;
即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。
中断(Interrupts)
__interruptdoublecompute_area(doubleradius){doublearea=PI*radius*radius;printf("\nArea=%f",area);returnarea;}
这个函数有太多的错误了,以至让人不知从何说起了:1)ISR不能返回一个值。如果你不懂这个,那么你不会被雇用的。2)ISR不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。4)与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
代码例子(Codeexamples)
12.下面的代码输出是什么,为什么?
voidfoo(void){unsignedinta=6;intb=-20;(a+b>6)puts(">6"):puts("<=6");}这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。
13.评价下面的代码片断:
unsignedintzero=0;unsignedintcompzero=0xFFFF;/*1'scomplementofzero*/
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsignedintcompzero=~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧...
动态内存分配(Dynamicmemoryallocation)
char*ptr;if((ptr=(char*)malloc(0))==NULL)puts("Gotanullpointer");elseputs("Gotavalidpointer");
这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Gotavalidpointer"。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。
Typedef
#definedPSstructs*typedefstructs*tPS;
以上两种情况的意图都是要定义dPS和tPS作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
dPSp1,p2;tPSp3,p4;
第一个扩展为
structs*p1,p2;.上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3和p4两个指针。晦涩的语法
16.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
inta=5,b=7,c;c=a+++b;
这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c=a+++b;
因此,这段代码持行后a=6,b=7,c=12。如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题。
华为笔试题1.写出判断ABCD四个表达式的是否正确,若正确,写出经过表达式中a的值(3分)inta=4;(A)a+=(a++);(B)a+=(++a);(C)(a++)+=a;(D)(++a)+=(a++);a=答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a)+=a;改后答案依次为9,10,10,11
13.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。循环链表,用取余操作做14.不能做switch()的参数类型是:switch的参数不能为实型。
華為1、局部变量能否和全局变量重名?答:能,局部会屏蔽全局。要用全局变量,需要使用"::"局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。
4、语句for(;1;)有什么问题?它是什么意思?答:无限循环,和while(1)相同。
5、do……while和while……do有什么区别?答:前一个循环一遍再判断,后一个判断以后再循环。
6、请写出下列代码的输出内容#include
2、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。
3、设有以下说明和定义:typedefunion{longi;intk[5];charc;}DATE;structdata{intcat;DATEcow;doubledog;}too;DATEmax;则语句printf("%d",sizeof(structdate)+sizeof(max));的执行结果是:___52____答:DATE是一个union,变量公用空间.里面最大的变量类型是int[5],占用20个字节.所以它的大小是20data是一个struct,每个变量分开占用空间.依次为int4+DATE20+double8=32.所以结果是20+32=52.当然...在某些16位编辑器下,int可能是2字节,那么结果是int2+DATE10+double8=20
4、队列和栈有什么区别?队列先进先出,栈后进先出
5、写出下列代码的输出内容#include
voidshow(FUNC2fun,intarg1,int*arg2){INCp=&inc;inttemp=p(arg1);fun(&temp,&arg1,arg2);printf("%d\n",*arg2);}
main(){inta;show(multi,10,&a);return0;}答:1107、请找出下面代码中的所以错误说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
1、#include"string.h"2、main()3、{4、char*src="hello,world";5、char*dest=NULL;6、intlen=strlen(src);7、dest=(char*)malloc(len);8、char*d=dest;9、char*s=src[len];10、while(len--!=0)11、d++=s--;12、printf("%s",dest);13、return0;14、}答:方法1:intmain(){char*src="hello,world";intlen=strlen(src);char*dest=(char*)malloc(len+1);//要为\0分配一个空间char*d=dest;char*s=&src[len-1];//指向最后一个字符while(len--!=0)*d++=*s--;*d=0;//尾部要加\0printf("%s\n",dest);free(dest);//使用完,应当释放空间,以免造成内存汇泄露return0;}方法2:#include 入队:将新元素push入栈A; 出队:(1)判断栈B是否为空;(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;(3)将栈B的栈顶元素pop出; 这样实现的队列入队和出队的平摊复杂度都还是O(1),比上面的几种方法要好。3.在c语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么?函数名:atol功能:把字符串转换成长整型数用法:longatol(constchar*nptr);程序例:#include l=atol(lstr);printf("string=%sinteger=%ld\n",str,l);return(0);} 微软亚洲技术中心的面试题!!!1.进程和线程的差别。线程是指进程内的一个执行单元,也是进程内的可调度实体.与进程的区别:(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。2.测试方法人工测试:个人复查、抽查和会审机器测试:黑盒测试和白盒测试 慧通:什么是预编译何时需要预编译:1、总是使用不经常改动的大型代码体。2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。char*constp;charconst*pconstchar*p 上述三个有什么区别?char*constp;//常量指针,p的值不可以修改charconst*p;//指向常量的指针,指向的常量值不可以改constchar*p;//和charconst*p charstr1[]="abc";charstr2[]="abc"; constcharstr3[]="abc";constcharstr4[]="abc"; constchar*str5="abc";constchar*str6="abc"; char*str7="abc";char*str8="abc"; cout<<(str1==str2)< 结果是:0011解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。 12.以下代码中的两个sizeof用法有问题吗?[C易]voidUpperCase(charstr[])//将str中的小写字母转换成大写字母{for(size_ti=0;i 一个32位的机器,该机器的指针是多少位指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。 main(){inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1));}输出:2,5*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)int*ptr=(int*)(&a+1);则ptr实际是&(a[5]),也就是a+5原因如下:&a是数组指针,其类型为int(*)[5];而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同a是长度为5的int数组指针,所以要加5*sizeof(int)所以ptr实际是a[5]但是prt与(&a+1)类型是不一样的(这点很重要)所以prt-1只会减去sizeof(int*)a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 1.请问以下代码有什么问题:intmain(){chara;char*str=&a;strcpy(str,"hello");printf(str);return0;}没有为str分配内存空间,将会发生异常问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。 1、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。.#defineMin(X,Y)((X)>(Y)(Y):(X))//结尾没有;2、嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。while(1){}或者for(;;)3、关键字static的作用是什么?定义静态变量4、关键字const有什么含意?表示常量不可以修改的变量。5、关键字volatile有什么含意?并举出三个不同的例子?提示编译器对象的值可能在编译器未监测到的情况下改变。 int(*s[10])(int)表示的是什么啊int(*s[10])(int)函数指针数组,每个指针指向一个intfunc(intparam)的函数。