2023年嵌入式软件笔试题_第1页
2023年嵌入式软件笔试题_第2页
2023年嵌入式软件笔试题_第3页
2023年嵌入式软件笔试题_第4页
2023年嵌入式软件笔试题_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

凹凸笔试题目(嵌入式软件开发)

2023-02-07

EmbeddedSoftwareDesignEngineer

1读程序段,回答问题

intmain(intargc,char*argv[])

(

intc=9,d=0;

c=c++%5;

d=c;

printf(,zd=%d\n/z,d);

return0;

)

a)写出程序输出

b)在一个可移植的系统中这种表达式是否存在风险?why?

#include〃stdio.h〃

inta=0;

intb;

staticcharc;

intmain(intargc,char*argv[])

(

chard=4;

staticshorte;

a++;

b=100;

c=(char)++a;

e=(++d)++;

printf(z,a=%d,b=%d,c=%d,d=%d,e=%d,z,a,b,c,d,e);

return0;

)

a)写出程序输出

b)编译器假如安排各个变量(a,b,c,d)在内存中的布局(eg.stack,heap,datasection,bss

section),最佳用图形方式描述。

2中断是嵌入式系统中重要的组成部分,这导致了许多编译开发商提供一种扩展:让标准C支持

中断,产生了一个新的关键字—interrupt。下面的代码就使用了—interrupt关键字去定义了一

个中断服务子程序(ISR),请评论以下这段代码。

_interruptdoublecompute_area(doub1eradius)

doublearea=PI*radius*radius;

printf("nArea=%f”,area);

returnarea;

}

3C/C++基础知识问题

a)关键字volatile在编译时有什么含义?并给出三个不同使用场景的例子(可以伪代码或者文字

描述)。

b)C语言中static关键字的具体作用有哪些?

c)请问下面三种变量声明有何区别?请给出具体含义

intconst*p;

int*constp;

intconst*constp;

4嵌入式系统相关问题

a)对于整形变量A=0xl2345678,请画出在littleendian及bigendian的方式下在内存中是如

何存储的。

b)在ARM系统中,函数调用的时候,参数是通过哪种方式传递的?

c)中断(interrupt,如键盘中断)与异常(exception,如除零异常)有何区别?

5设周期性任务P1,P2,P3的周期为T1,T2,T3分别为100,150,400;执行时间分别为20,40,100。

请设计一种调度算法进行任务调度,满足任务执行周期及任务周期。

6优先级反转问题在嵌入式系统中是一中严重的问题,必须给与足够重视。

a)一方面请解释优先级反转问题

b)很多RTOS提供优先级继承策略(Priorityinheritance)和优先级天花板策略(Priority

ceilings)用来解决优先级反转问题,请讨论这两种策略。

参考答案:

15

存在风险,由于c=c++%5;这个表达式对c有两次修改,行为未定义,c的值不拟定

inta=0;//datasection

intb;//datasection

staticcharc;//BSS

intmain(intargc,char*argv[])

(

chard=4;//stack

staticshorte;//BSS

a++;

b=100;

c=(char)++a;

e=(++d)++;

printf(z/a=%d,b=%d,c=%d,d=%d,e=%d”,a,b,c,d,e);

return0;

a=2,b=100,c=2,d=6,e=5

2a)ISR不能返回一个值;

b)ISR不能传递参数;

c)浮点一般都是不可重入的;

cDprintf函数有重入和性能上的问题。

3a)用volatile关键字定义变量,相称于告诉编译器,这个变量的值会随时发生变化,每次使

用时都需要去内存里

重新读取它的值,并不要随意针对它作优化。

建议使用volatile变量的场合:

(1)并行设备的硬件寄存器

(2)一个中断服务子程序中会访问到的非自动变量(全局变量)

(3)多线程应用中被几个任务共享的变量

b)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能

被模块外其它函数

访问。它是一个本地的全局变量。

在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数

被限制在声明它的

模块的本地范围内使用。

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其

他文献单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依

据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调

用中维持一份拷贝

c)一个指向常整型数的指针

一个指向整型数的常指针

一个指向常整型数的常指针

4

a)0x12345678

littleendianbigendian刚好反过来

高地址一〉0x12低地址一〉0x12

0x340x34

0x560x56

低地址一〉0x78高地址一〉0x78

b)参数〈=4时候,通过R0“R3传递,>4的通过压栈方式传递

c)异常:在产生时必须考虑与解决器的时钟同步,实践上,异常也称为同步中断。在解决器执

行到由于编程失误而导致的错误指令时,或者在执行期间出现特殊情况(如缺页),必须靠内核解

决的时候,解决器就会产生一个异常。

所谓中断应当是指外部硬件产生的一个电信号,从cpu的中断引脚进入,打断cpu当前的运营;

所谓异常,是指软件运营中发生了一些必须作出解决的事件,CPU自动产生一个陷入来打断当前

运营,转入异常解决流程。

异步与同步的区别,

5

6高优先级任务需要等待低优先级任务释放资源,而低优先级任务又正在等待中档优先级任务的

现象叫做优先级反转

优先级继承策略(Priorityinheritance):继承现有被阻塞任务的最高优先级作为其优先级,任

务退出临界区,恢

复初始优先级。

优先级天花板策略(Priorityceilings):控制访问临界资源的信号量的优先级天花板。

优先级继承策略对任务执行流程的影响相对教小,由于只有当高优先级任务申请已被低优先级

任务占有的临界资源

这一事实发生时,才抬升低优先级任务的优先级。

2)数据类型

char一个字节1byte

int两个字节2byte(16位系统,认为整型是24

longint四个字节4byte

float四个字节4byet

double八个字节8byte

longdouble十个字节10byte

pointer两个字节2byte(注意,16位系统,地址

第1题:考核对volatile关键字的结识

#include<setjmp.h>

staticjmp_bufbuf;

main()

volatileintb;

b=3;

if(setjmp(buf)!=0)

(

printf(**%d”,b);

exit(0);

)

b=5;

longjmp(buf,1);

)

请问,这段程序的输出是

(a)3

(b)5

(c)0

(d)以上均不是

第2题:考察类型转换

main()

(

structnode

(

inta;

intb;

intc;

);

structnodes={3,5,6};

structnode*pt=&s;

printf(,'%dn,*(int*)pt);

这段程序的输出是:

(a)3

(b)5

(c)6

(d)7

第3题:考察递归调用

intfoo(intx,intn)

intval;

val=1;

if(n>0)

if(n%21)val=val*x;

val=val*foo(x*x,n/2);

returnval;

这段代码对X和n完毕什么样的功能(操作)?

(a)x~n(x的n次某)

(b)x*n(x与n的乘积)

(c)n-x(n的x次事)

(d)以上均不是

第4题:考察指针,这道题只适合于那些特别细心且对指针和数组有进一步理解的人

main()

(

inta[5]={1,2,3,4,5};

int*ptr=(int*)(&a+l);

printf(n%d,*(a+1),*(ptr-1));

这段程序的输出是:

(a)22

(b)21

(c)25

(d)以上均不是

第5题:考察多维数组与指针

voidfoo(int[][3]);

main()

(

inta[3][3]={{1,2,3},{4,5,6},{7,8,9}};

foo(a);

printf(n%dn,a[2][1]);

)

voidfoo(intb[][3])

(

++b;

b[l][1]=9;

这段程序的输出是:

(a)8

(b)9

(c)7

(d)以上均不对

第6题目:考察逗号表达式

main()

{

inta,bzc,d;

a=3;

b=5;

c=a,b;

d=(a,b);

printf(Hc=%d",c);

printf(Hd=%d",d);

这段程序的输出是:

(a)c=3d=3

(b)c=5d=3

(c)c=3d=5

(d)c=5d=5

第7题:考察指针数组

main()

inta[][3]={1,2,3,4,5,6};

int(*ptr)[3]=a;

Hn

printf(%d%dz(*ptr)[1],(*ptr)[2]);

++ptr;

printf(n%d%d",(*ptr)[1],(*ptr)[2]);

)

这段程序的输出是:

(a)2356

(b)2345

(c)4500

(d)以上均不对

第8题:考察函数指针

int*f1(void)

(

intx=10;

return(&x);

)

int*f2(void)

(

int*ptr;

*ptr=10;

returnptr;

)

int*f3(void)

{

int*ptr;

ptr=(int*)malloc(sizeof(int));

returnptr;

)

上面这3个函数哪一个最也许引起指针方面的问题

(a)只有f3

(b)只有flandf3

(c)只有flandf2

(d)fl,f2,f3

第9题:考察自加操作(++)

main()

inti=3;

intj;

j=sizeof(++i+++i);

H

printf(i=%dj=%d"zi,j);

)

这段程序的输出是:

(a)i=4j=2

(b)i=3j=2

(c)i=3j=4

(d)i=3j=6

第10题:考察形式参数,实际参数,指针和数组

voidfl(int*,int);

voidf2(int*,int);

void(*p[2])(int*,int);

main()

inta;

intb;

p[0]=fl;

Ptl]=f2;

a=3;

b=5;

p[0](&a,b);

printf(**%d\t%d\t",a,b);

p(l](&a,b);

printf(n%d\t%d\t",a,b);

}

voidfl(int*p/intq)

(

inttmp;

tmp=*p;

*P=q;

q=tmp;

)

void£2(int*p,intq)

(

inttmp;

tmp=*p;

*p=q;

q=tmp;

这段程序的输出是:

(a)5555

(b)3535

(c)5353

(d)3333

第11题:考察自减操作(一)

voide(int);

main()

(

inta;

a=3;

e(a);

)

voide(intn)

if(n>0)

e(——n);

printf(K%dn,n)

e(——n);

)

这段程序的输出是:

(a)0120

(b)0121

(c)1201

(d)0211

第12题:考察typedef类型定义,函数指针

typedefint(*test)(float*,float*)

testtmp;

tmp的类型是

(a)函数的指针,该函数以两个指向浮点数(float)的指针(pointer)作为参数

(arguments)

Pointertofunctionofhavingtwoargumentsthatispointertofloat

(b)整型

(c)函数的指针,该函数以两个指向浮点数(float)的指针(pointer)作为参数

(arguments),并且函数的返回值类型是整型

Pointertofunctionhavingtwoargumentthatispointertofloatand

returnint

(d)以上都不是

第13题:数组与指针的区别与联系

main()

(

charp;

charbuf[10]={1,2,3,4,5,6,9,8};

p=(buf+1)[5];

printf(n%dn,p);

这段程序的输出是:

(a)5

(b)6

(c)9

(d)以上都不对

第14题:考察指针数组的指针

Voidf(char**);

main()

{

char*argv[]={"ab","cd”,nefu,"gh",nijn,"kl");

f(argv);

)

voidf(char**p)

(

char*t;

t=(p+=sizeof(int))[-1];

printf(n%sn,t);

)

这段程序的输出是:

(a)ab

(b)cd

(c)ef

(d)gh

第15题:此题考察的是C的变长参数,就像标准函数库里printf()那样,这个话题一般国

内大学课堂是不会讲到的,不会也情有可原呵呵,

#include<stdarg.h>

intripple(int,...);

main()

(

intnum;

num=ripple(3,5,7);

printf(",num);

)

intripple(intn,...)

(

inti,j;

intk;

va_listp;

k=0;

j=1;

va_start(p,n);

for(;j<n;++j)

iva_arg(p,int);

for(;i;i&=i-l)

++k;

)

returnk;

)

这段程序的输出是:

(a)7

(b)6

(c)5

(d)3

第16题:考察静态变量的知识

intcounter(inti)

(

staticintcount=0;

count=count+i;

return(count);

)

main()

(

inti,j;

for(i=0;i<=5;i++)

j=counter(i);

)

本程序执行到最后,j的值是:

(a)10

(b)15

(c)6

(d)7

具体参考答案

第1题:(b)

volatile字面意思是易于挥发的。这个关键字来描述一个变量时,意味着给该变量赋

值(写入)之后,立即再读取,写入的值与读取的值也许不同样,所以说它''容易挥发''的。

这是由于这个变量也许一个寄存器,直接与外部设备相连,你写入之后,该寄存器也

有也许被外部设备的写操作所改变;或者,该变量被一个中断程序,或另一个进程

改变了.

volatile不会被编译器优化影响,在longjump后,它的值是后面假定的变量值,b最

后的值是5,所以5被打印出来.

setjmp:设立非局部跳转/*setjmp.h*/

Storescontextinformationsuchasregistervaluessothatthelomgjmpfunction

canreturncontroltothestatementfollowingtheonecallingsetjmp.Returns

0whenitisinitiallycalled.

Lonjjmp:执行一个非局部跳转/*setjmp.h*/

Transferscontroltothestatementwherethecalltosetjmp(whichinitialized

buf)wasmade.Executioncontinuesatthispointasiflongjmpcannotreturn

thevalue0.Anonvolatileautomaticvariablemightbechangedbyacallto

longjmp.Whenyouusesetjmpandlongjmp,theonlyautomaticvariables

guaranteedtoremainvalidarethosedeclaredvolatile.

Note:Testprogramwithoutvolatilequalifier(resultmayvery)

更具体介绍,请参阅C语言的setjmp和longjmp

第2题:(a)

结构题的成员在内存中的地址是按照他们定义的位置顺序依次增长的。假如一个结构

体的指针被当作它的第一个成员的指针,那么该指针的确指向第一个成员

第3题:(a)

此题目较难.

这个程序的非递归版本

intwhat(intx,intn)

{

intval;

intproduct;

product=1;

val=x;

while(n>0)

(

if(n%2==1)

product=product*val;/*假如是奇数次基,x(val)

要先乘上一次,;

偶数次幕,最后返回时才会到这里

乘以1*/

val=val*val;

n=n/2;

)

returnproduct;

/*用二元复乘策略*/

算法描述

(whilen>0)

ifnextmostsignificantbinarydigitofn(power)isone

thenmultiplyaccumulatedproductbycurrentval,

reducen(power)sequencebyafactoroftwousingintegerdivision.

getnextvalbymultiplycurrentvalueofitself

)

第4题:(c)

a的类型是一个整型数组,它有5个成员

&a的类型是一个整型数组的指针

所以&a+1指向的地方等同于a[6]

a[l]=*(a+l)ptr-1&a+l

所以*(a+l)等同于a[l]

ptr等同a[6],ptrT就等同与a[5]

第5题:(b)

a[0]a[l]a[2]a[2][l]

123456799

++bb[l][l]=9

题目自身就给了足够的提醒

b[0][0]=4

b[l][0]=7

第6题:(c)

考察逗号表达式,逗号表达式的优先级是很低的,比赋值(=)的优先级低.逗号表达

式的值就是最后一个元素的值

逗号表达式的尚有一个作用就是分割函数的参数列表..

El,E2,...,En

上面这个表达式的左右是,El,E2,...En的值被分别计算出来,En计算出来的结构赋

给整个逗号表达式

c=a,b;/*yieldsc=a*/

d=(a,b);/*d=b*/

第7题:(a)

研0]a[l]

ptr-H-ptr

ptr是一个数组的指针,该数组有3个int成员

第8题:(c)

fl显然有问题,它返回一个局部变量的指针,局部变量是保存在stack中的,退出函数

后,局部变量就销毁了,保存其指针没故意义,由于其指向的stack空间也许被其他

变量覆盖了

f2也有问题,ptr是局部变量,未初始化,它的值是未知的,*ptr不知道指向哪里了,

直接给*ptr赋值也许会覆盖重要的系统变量,这就是通常说的野指针的一种

第9题:(b)

sizeof操作符给出其操作数需要占用的空间大小,它是在编译时就可拟定的,所以

其操作数即使是一个表达式,也不需要在运营时进行计算.(++i+++i)是不会执

行的,所以

i的值还是3

第10题:(a)

很显然选a.

门互换*P和q的值,fl执行完后,*p和q的值的确互换了,但q的改变不会影响

到b的改变,*p事实上就是a

所以执行fl后,a=b=5

这道题考察的知识范围很广,涉及typedef自定义类型,函数指针,指针数组

void(*p[2])(int*,int);

定义了一个函数指针的数组P,P有两个指针元素.元素是函数的指针,函数指针指向

的函数是一个带2个参数,返回void的函数,所带的两个参数是指向整型的指针,和

整型

p[0]=fl;p[1]=f2containaddressoffunction.functionnamewithout

parenthesisrepresentaddressoffunctionValueandaddressofvariableis

passedtofunctiononlyargumentthatiseffectedisa(addressispassed).

Becauseofcallbyvaluefl,f2cannoteffectb

第11题:(a)

e(—1)terminates

]prin而“%d",0);

e(—0)terminates

I

e(—3)---------prin氓"

printf("%d",2);e(—1Z)terminates

e(-2)匚

,、、、e(—1)terminates

prin般"%d”,0);

}|e(-)terminates

考察一操作和递归调用,仔细分析一下就可以了

第12题:(c)

建议不会的看看C专家编程

从左往有,碰到括号停下来,将第一个括号里的东西当作一个整体

第13题:(c)

考察什么时候数组就是指针.对某些类型T而言,假如一个表达式是T[](T的数组),这

个表达式的值事实上就是指向该数组的第一个元素的指针.所以(buf+1)[5]事实上就是

*(buf+6)或者buf[6]

第14题:(b)

sizeof(int)的值是2,所以p+=sizeof(int)指向argv[2],这点估计大家都没有什么疑问

(p+=sizeof(int))[-1]指向argv[l],能理解吗,由于(p+=sizeof(int))[T]就相称于

(p+=,也就是(p+2-1)

第15题:(c)

在C编译器通常提供了一系列解决可变参数的宏,以屏蔽不同的硬件平台导致的差异,增长

程序的可移植性。这些宏涉及va_start>va_arg和va_end等。

采用ANSI标准形式时,参数个数可变的函数的原型声明是:

typefuncname(typeparal,typepara2,...)

这种形式至少需要一个普通的形式参数,后面的省略号不表达省略,而是函数原型的一部分。

type是函数返回值和形式参数的类型。

不同的编译器,对这个可变长参数的实现不同样,gcc4.x中是内置函数.

关于可变长参数,可参阅

[url][/url]

[url][/url]

程序分析

va_listp;/*定义一个变量,保存函数参数列表的指针*/

va_start(p,n);/*用va_start宏初始化变量p,

va_start宏的第2个参数n,

是一个固定的参数,

必须是我们自己定义的变长函数的最后一个入栈的参数

也就是调用的时候参数列表里的第1个参数*/

for(;j<n;++j)/*j从1开始,遍历所有可变参数*/

vaarg(p,int);/*vaarg取出当前的参数,

并认为取出的参数是一个整数(int)*/

for(;i;i&=i-l)/*判断取出的i是否为0*/

++k;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论