百度文库百度文库1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。#defineSECONDS_PER_YEAR(365*24*60*60)UL2.写一个标准宏MIN,这个宏输入两个参数并返回较小的一个。#defineMIN((A)=(B)?(A):(B))3.预处理器标识#error的目的是什么?#error记号序列将使预处理器打印包含该记号序列的诊断信息。4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?While(1){}5.用变量a给出下面的定义a)一个整型数(Aninteger)b)一个指向整型数的指针(Apointertoaninteger)c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoanintege)rd)一个有10个整型数的数组(Anarrayof10integers)e)一个有10个指针的数组,该指针是指向一个整型数的。(Anarrayof10pointerstointegers)f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnaninteger)a)inta;b)int*a;c)int**a;d)inta[10];e)int*a[10];f)int(*a)[10];g)int(*a)(int);h)int(*a[10])(int);6.关键字static的作用是什么?答:1)在函数体内,被声明为静态的变量在函数内被调用的过程中维持值不变,这个局部变量存储域发生改变,从栈到data中,所以这个值不变。(static局部变量只被初始化一次,下一次依据上一次结果值;2)在模块内被声明的静态全局变量,能被模块内部声明之后的函数调用,但不能被模块外的函数调用。这是一个本地的变量。所以声明为静态的全局变量的作用域发生改变,限制了它的使用范围。3)在模块内的声明的静态函数,可以被模块内部的其他函数调用,但不可被模块外部的函数调用。也就是这个函数被限制在声明它的模块使用。对于可在原模块外部使用的函数,应该在一个头文件中说明,要使用这些函数的模块需包含这个头文件。7.关键字const有什么含意?1)使用Const关键字的地方是为了说明这个参数为常量,是不应该被修改的。2)合理使用const可以是编译器自然的保护那些不希望被修改的参数,防止被无意的代码百度文库百度文库修改。3)通过给优化器一些有用的信息,使用关键字const也许是代码更加紧凑。题:1.有以下表达式:inta=248;b=4;intconstc=21;constint*d=&a;int*conste=&b;intconst*fconst=&a;请问下列表达式哪些会被编译器禁止?为什么?*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;*c这是个什么东东,禁止*d说了是const,禁止e=&a说了是const禁止const*fconst=&a;禁止下面的声明都是什么意思?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的变量就是说它可能会意想不到的改变(改变它的情况有很多,例如操作系统,硬件,线程),这样,编译器就不会去假设这个值,也就是说,当优化器读到这个值时就会小心翼翼的去重新读取这个变量的值,而不是使用保存在寄存器中的备份。(当使用到用类型修饰符声明的变量时,系统总是从它所在的内存读取,既使系统刚从这里读取过)Volatile修饰符告诉编译程序不要对该变量所参与的操作进行优化。大多数计算机拥有一系列寄存器,其存取速度比计算机主存更快。好的编译程序能进行一种被称为“冗余装入和存储的删去”(redundantloadandstoreremoval)的优化,即编译程序会在程序中寻找并删去这样两类代码:一类是可以删去的从内存装入数据的指令,因为相应的数据已经被存放在寄存器中;另一种是可以删去的将数据存入内存的指令,因为相应的数据在再次被改变之前可以一直保留在寄存器中。例如:volatilei=10;inta=i;百度文库百度文库例子:1)并行设备的硬件寄存器。存储器映射的硬件寄存器通常加volatile例如状态寄存器。以为设备寄存器会在你的程序不知道或者不介入的时候发生改变,那是因为设备寄存器可以被外设硬件修改。相反,变量中的不会变。设备寄存器的内容是易失的,或者在不注意的时候被修改。当声明指向设备寄存器的指针时一定要用volatile它会告诉编译器不要对存储在这个地址的数据进行假设,编译器在优化这个变量时应该把它看作编译时未知的。#defineIOPMOD(*((Volatileunsigned*)(SYSCFG+0x5000)))2)一个中断服务程序中修改的供其他程序检测的变量。3)多线程应用中被几个任务共享的变量。1.一个变量可以既是const还是volatile吗?解释为什么?可以,例如状态寄存器。它首先应该是volatile因为它可以出乎意料的修改,而且应该是const,这个寄存器程序不应该去修改。2.一个指针可以说volatile的吗?可以,例如中断服务子程序中修改一个指向buffer的指针。3.下列代码有错误吗?Intsquare(volatileint*ptr){Return*ptr**ptr;}答:由于ptr声明为volatile类型的所以编译器可能编译完的程序是:intsquare(volatileint*ptr){inta,b;a=*ptr;b=*ptr;returna*b;}则得出的结果可能不是想要的结果;正确的程序这样写:longsquare(volatileint*ptr){inta;a=*ptr;returna*a;}9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。#defineBIT3(0x013)Staticinta;Voidset_bit3(void){a|=BIT3;}百度文库百度文库Voidclear_bit3(void){a&=~BIT3;}10.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。这一题目是测试你是否知道为了访问一绝对地址而把一个整型数强制转换成一个指针。int*ptr;ptr=(int*)0x67a9;*ptr=0xaa66;或者:*(int*const)(0x67a9)=0xaa66;11.中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。__interruptdoublecompute_area(doubleradius){Doublearea=pi*radius*radius;Printf(“\narea=%f”,area);Returnarea;}1)ISR是不能有返回值。2)ISR不能传递参数。3)在许多的处理器/编译器中,浮点一般都是不可重入的。ISR一般是短而有效的,在ISR中做浮点运算时不明智的。4)Printf()函数有重入和性能上的问题。12.下面的代码输出是什么,为什么?Voidfoo(void){Unsignedinta=6;Intb=-20;(a+b6)?(“6):(“6);}答案是“》6”原因是当操作数中有符号类型和无符号类型进行运算时所有的操作数都自动转换成无符号数。13.评价下面的代码片断:Unsignedintzero=0;Unsignedintcompzero=0xFFFF;对于int不是16位的处理器来说此代码不正确。应该写成:Unsignedintcompzero=~0;这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,14.尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么百度文库百度文库嵌入式系统中,动态分配内存可能发生的问题是什么?下面的代码片段的输出是什么,为什么?Char*ptr;if((ptr=(char*)malloc(0))==NULL)puts(Gotanullpointer);elseputs(Gotavalidpointer);15Typedef在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:15Typedef在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:#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:分别给出BOOL,int,float,指针变量与“零值”比较的if语句(假设变量名为var)解答:BOOL型变量:if(!var)int型变量:if(var==0)float型变量:constfloatEPSINON=0.00001;if((x=-EPSINON)&&(x=EPSINON)指针变量:if(var==NULL)剖析:考查对0值判断的“内功”,BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。一般的,如果想让if判断一个变量的“真”、“假”,应直接使用if(var)、if(!var),表明其为“逻辑”判断;如果用if判断一个数值型变量(short、int、long等),应该用