嵌入式软件工程师笔试题.docx

上传人:b****1 文档编号:2662014 上传时间:2023-05-04 格式:DOCX 页数:27 大小:64.01KB
下载 相关 举报
嵌入式软件工程师笔试题.docx_第1页
第1页 / 共27页
嵌入式软件工程师笔试题.docx_第2页
第2页 / 共27页
嵌入式软件工程师笔试题.docx_第3页
第3页 / 共27页
嵌入式软件工程师笔试题.docx_第4页
第4页 / 共27页
嵌入式软件工程师笔试题.docx_第5页
第5页 / 共27页
嵌入式软件工程师笔试题.docx_第6页
第6页 / 共27页
嵌入式软件工程师笔试题.docx_第7页
第7页 / 共27页
嵌入式软件工程师笔试题.docx_第8页
第8页 / 共27页
嵌入式软件工程师笔试题.docx_第9页
第9页 / 共27页
嵌入式软件工程师笔试题.docx_第10页
第10页 / 共27页
嵌入式软件工程师笔试题.docx_第11页
第11页 / 共27页
嵌入式软件工程师笔试题.docx_第12页
第12页 / 共27页
嵌入式软件工程师笔试题.docx_第13页
第13页 / 共27页
嵌入式软件工程师笔试题.docx_第14页
第14页 / 共27页
嵌入式软件工程师笔试题.docx_第15页
第15页 / 共27页
嵌入式软件工程师笔试题.docx_第16页
第16页 / 共27页
嵌入式软件工程师笔试题.docx_第17页
第17页 / 共27页
嵌入式软件工程师笔试题.docx_第18页
第18页 / 共27页
嵌入式软件工程师笔试题.docx_第19页
第19页 / 共27页
嵌入式软件工程师笔试题.docx_第20页
第20页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

嵌入式软件工程师笔试题.docx

《嵌入式软件工程师笔试题.docx》由会员分享,可在线阅读,更多相关《嵌入式软件工程师笔试题.docx(27页珍藏版)》请在冰点文库上搜索。

嵌入式软件工程师笔试题.docx

嵌入式软件工程师笔试题

维数组空间的动态申请

a.简单的,已经有一维,如

char(*c)[5];

c=newchar[n][5];维的

int**p;

p=newint*[m_row];

题二:

读程序,写出运行结果

#inelude<>

#include<>

#include<>

#include<>

typedefstruct

{

intvalue;

/chartype;

}head_t;这是什么东西啊?

typedefstruct

{

head_thead;

intpara;

}message_t;

voidmain(void)

{

message_t*message二NULL;

\head_t*head=NULL;

message=(message_t*)malloc(sizeof(message_t));

oassert(message);目标文件,不进行连接(一般很少单独使用)。

omakeclean

删除编译产生的目标文件和依赖文件。

omakecleanail

删除目标文件、依赖文件以及可执行文件。

omakerebuild

重新编译和连接程序。

相当于makeclean&&makeall。

下面提供两个例子来具体说明上面Makefile的用法。

例一HelloWorld程序

这个程序的功能是输出Hello,world!

这样一行文字。

由、、三个文件组成。

前两

个文件是C程序,后一个是C++程序,因此这是一个C和C++混编程序。

代码:

/*Filename:

*Cheaderfile

*/#ifndefHELLOH

#define

HELLO_H

#ifdef__cplusplus\

extern"C"{#endif

void

print_hello();

#ifdef__cplusplus

}#endif#endif

代码:

/*Filename:

Csourcefile.

*/#inelude""

voidprint_hello()

puts("Hello,world!

");

#include<>}

代码:

int

/*Filename:

*C++sourcefile.*/#include""

main(){print_hello();return0;}

建立一个新的目录,然后把这三个文件拷贝到目录中,也把Makefile文件拷贝到目

录中。

之后,对Makefile的相关项目进行如卞设置:

代码:

PROGRAM:

=hello

SRCDIRS:

=.

SRCEXTS:

=.c.cxx

CFLAGS:

=-g

CXXFLAGS:

=-g信息

#设置运行程序名

#源程序位于当前目录下

#源程序文件有.c和.cxx两种类型

#为C目标程序包含GDB可用的调试信息

#为C++目标程序包含GDB可用的调试

由于这个简单的程序只使用了C标准库的函数(puts),所以对于CFLAGS和

CXXFLAGS没有过多的要求,LDFLAGS和CPPFLAGS选项也无需设置。

经过上面的设置之后,执行make命令就可以编译程序了。

如果没有错误出现的

话,./hello就可以运行程序了。

如果修改了源程序的话,可以看到只有和修改有关的源文件被编译。

也可以再为程序

添加新的源文件,只要它们的扩展名是已经在Makefile中设置过的,那么就没有必

要修改Makefile。

1.引言

本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵。

文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见。

许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。

企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度,我们能真正写好一个strcpy函数吗?

我们都觉得自己能,可是我们写出的strcpy很可能

只能拿到10分中的2分。

读者可从本文看到strcpy函数从2分到10分解答的例子,看看自己属于什么样的层次。

此外,还有一些面试题考查面试者敏捷的思维能力。

分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。

2.找错题

试题1:

voidtest1(){charstring[10];char*str1="09";

strcpy(string,str1);}

试题2:

八——

voidtest2(){charstring[10],str1[1O];inti;for(i=0;

i<10;i++){str1[i]='a';}strcpy(string,

stri);}

试题3:

voidtest3(char*str1){charstring[10];if(strlen(str1)

<=10){strcpy(string,str1);}}

解答:

试题1字符串str1需要11个字节才能存放下(包括末尾的’0',而string只有10个字节的空间,strcpy会导致数组越界;

对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,str1)调用使得从str1内存起复制到string内存起所复制的

字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;

对试题3,if(strlen(str1)<=10)应改为if(strlen(str1)<10),因为strlen的结果未统计’0’所占用的1个字节。

剖析:

\

考查对基本功的掌握:

(1)字符串以'0'吉尾;

(2)对数组越界把握的敏感度;

(3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,

下面给出几个不同得分的答案:

2分

voidstrcpy(char*strDest,char*strSrc){

while((*strDest++=*strSrc++)!

=0');}

4分

voidstrcpy(char*strDest,constchar*strSrc)0'

 

 

 

 

功题

试题1:

分别给出BOOL,int,float,指针变量与零值”比较的if语句(假设变量名为var)/\

解答:

BOOL型变量:

if(!

var)|_Z\

int型变量:

if(var==0)

float型变量:

constfloatEPSINON=;

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等),应该用if(var==0),表明是与0进行数值”上的比较;而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯。

浮点型变量并不精确,所以不可将float变量用“==”或!

二”与数字比较,应该

设法转化成“>=”或“<=”形式。

如果写成if(x==,则判为错,得0分。

\

试题2:

以下为WindowsNT下的32位C++程序,请计算sizeof的值\

voidFunc(charstr[100]){

sizeof(str)=?

}

void*p=|

malloc(100);sizeof(p)=?

解答:

sizeof(str)=4sizeof(p)=4

咅U析:

\一_一_一

Func(charstr[100])函数中数组名作为函数形参时,在函数体内,数组名失

去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

X

数组名的本质如下:

/

(1)数组名指代一种数据结构,这种数据结构就是数组;

例如:

charstr[10];cout<

输出结果为10,str指代数据结构char[10]。

(2)

charstr[10];

sM++;

数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;

头文件中的编译宏

的作用是防止被重复引用。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。

函数被C++编译后在symbol库中的名字与C语言的不同。

例如,假设某个函数的原型为:

该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo」nt_int之类的名字。

_foo」nt_int这样的名字包含了函数名和函数参数数

量及类型信息,C++就是考这种机制来实现函数重载的。

voidfoo(intx,inty);

为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern"C"来解决名字匹配问题,函数声明前加上extern"C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了试题5:

编写一个函数,作用是把一个char组成的字符串循环右移n个。

比如原来是

“abcdefghi如果n=2,移位后应该是“hiabcdefgh

函数头是这样的:

解答:

正确解答1:

voidLoopMove(char*pStr,intsteps){intn二strlen(pStr)

-steps;chartmp[MAXLEN];

 

 

 

 

 

巧题

试题1:

请写一个C函数,若处理器是Big_endian的,则返回0;若是

Little_endian的,则返回/

解答:

\

intcheckCPU(){{unionw{inta;

charb;}c;=1;0X00000001四个字节,为一个字节

return==1);大端的为00,小端的为01?

?

?

?

}

类”的概念,也很容易理解void数据类型。

正如不能给抽象基类定义一个实例,我们也不能定义一个void(让我们类比的称void为抽象数据类型”)变量。

关于CONST的用法

const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable)。

我们来分情况看语法上它该如何被使用。

1、函数体内修饰局部变量。

例:

voidfunc(){

constinta=0;

}、、亠、首先,我们先把const这个单词忽略不看,那么a是一个int类型的局部自动变量,我们给它赋予初始值0。

然后再看const.

const作为一个类型限定词,和int有相同的地位。

constinta;

intconsta;

是等价的。

于是此处我们一定要清晰的明白,const修饰的对象是谁,是a,和int没

有关系。

const要求他所修饰的对象为常量,不可被改变,不可被赋值,不可作为

左值(l-value)。

这样的写法也是错误的。

constinta;

a=0・

这是一个很常见的使用方式:

constdoublepi=;

在程序的后面如果企图对pi再次赋值或者修改就会出错。

然后看一个稍微复杂的例子。

constint*p;

还是先去掉const修饰符号。

注意,下面两个是等价的。

int*p;int*p;

其实我们想要说的是,*p是int类型。

那么显然,p就是指向int同理

constint*p;

其实等价于

constint(*p);

intconst(*p);

即,*p是常量。

也就是说,p指向的数据是常量。

于是p+=8;代表什么。

如果去掉const,我们可以看出

char*argv[];

argv是一个数组,它的每个元素都是char*类型的指针。

如果加上const.那么const修饰的是谁呢?

他修饰的是一个数组,说这个数组的元素是只读的。

那么数组的元素的是什么类型呢?

是针•也就是说指针是常量,而它指向的数据不是。

于是

argv[1]=NULL;用extern

例如

/**/

externconstdoublepi;

/**/

constdoublepi=;

然后其他需要使用pi这个变量的,包含

#include""

或者,自己把那句声明复制一遍就好。

这样做的结果是,整个程序链接完后,所有需要使用pi这个变量的共享一个存储区域。

2.使用static,静态外部存储类

/**/

staticconstpi=;

的指针。

argv[],意思就是

char*类型的指

 

需要使用这个变量的*.c文件中,必须包含这个头文件。

前面的static一定不能少。

否则链接的时候会报告说该变量被多次定义。

这样做的结果是,每个包含了的*.c文件,都有一份该变量自己的copy,

该变量实际上还是被定义了多次,占用了多个存储空间,不过在加了static关键字

后,解决了文件间重定义的冲突。

坏处是浪费了存储空间,导致链接完后的可执行文件变大。

但是通常,这个,小小几字节的变化,不是问题。

好处是,你不用关心这个变量是在哪个文件中被初始化的。

最后,说说const的作用。

const的好处,是引入了常量的概念,让我们不要去修改不该修改的内存。

直接的作用就是让更多的逻辑错误在编译期被发现。

所以我们要尽可能的多使用const。

但是很多人并不习惯使用它,更有甚者,是在整个程序编写/调试完后才补

const。

如果是给函数的声明补const,尚好。

如果是给全局/局部变量补const,那么••…那么,为时已晚,无非是让代码看起来更漂亮了。

c语言中的结构(struct)和联合(union)简介

联合(union)

1.联合说明和联合变量定义

联合也是一种新的数据类型,它是一种特殊形式的变量。

联合说明和联合变量定义与结构十分相似。

其形式为:

union联合名{

数据类型成员名;

数据类型成员名;

}联合变量名;

联合表示几个变量公用一个内存位置,在不同的时间保存不同的数据类型和不同长

度的变量。

下例表示说明一个联合a_bc:

uniona_bc{

inti?

charmm;

};

再用已说明的联合可定义联合变量。

例如用上面说明的联合定义一个名为lgc的联合变量,可写成:

uniona_bclgc;\/

在联合变量lgc中,整型量i和字符mm公用同一内存位置。

当一个联合被说明时,编译程序自动地产生一个变量,其长度为联合中最大的变量长度。

联合访问其成员的方法与结构相同。

同样联合变量也可以定义成数组或指针,但定义

为指针时,也要用"->;"符号,此时联合访问成员可表示成:

联合名->;成员名

另外,联合既可以出现在结构内,它的成员也可以是结构。

例如:

struct{

intage;

char*addr;

union{

inti;

char*ch;

}x;

理叫、「冃

若要访问结构变量y[1]中联合x的成员i,可以写成:

y[i].;

若要访问结构变量y[2]中联合x的字符串指针ch的第一个字符可写成:

*y[2].;

若写成"y[2].x.*ch;"是错误的。

2.结构和联合的区别

结构和联合有下列区别:

1.结构和联合都是由多个不同的数据类型成员组成,但在任何同一时刻,联合转只存放了一个被选中的成员,而结构的所有成员都存在。

2.对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于结构的不同成员赋值是互不影响的。

下面举一个例了来加对深联合的理解。

例4:

main()

{

union{/*定义一个联合*/

inti;

struct{/*在联合中定义一个结构*/

charfirst;

charsecond;

}half;

}number;

=0x4241;/*联合成员赋值*/

printf("%c%c\n",

'a';/*联合中结构成员赋值*/

'b';

printf("%x\n",;

getch();

}

输出结果为:

AB

6261

从上例结果可以看出:

当给i赋值后,其低八位也就是first和second的值;当给first和second赋字符后,这两个字符的ASCII码也将作为i的低八位和高八位。

Volatile关键字告诉编译器不要持有变量的临时性拷贝。

一般用在多线程程序中,以

避免在其中一个线程操作该变量时,将其拷贝入寄存器。

请看以下情形:

A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条

件(它期待B线程改变变量的值。

在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。

所以A线程进入死循环。

volatile就是在此种情况下使用。

一、预备知识一程序的内存分配

一个由C/C++编译的程序占用的内存分为以下几个部分

1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。

其操作方式类似于数据结构中的栈。

2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。

3、全局区(静态区)(static)―,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

-程序结束后有系统释放

4、文字常量区一常量字符串就是放在这里的。

程序结束后由系统释放

5、程序代码区一存放函数体的二进制代码。

例子程序这是一个前辈写的,非常详细另外,在WINDOWS下,最好的方

式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。

但是速度快,也最灵活。

堆和栈中的

存储内容栈:

在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编

译器中,参数是由右往左入栈的,然后是函数中的局部变量。

注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指

向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

堆:

一般是在堆的头部用一个字节存放堆的大小。

堆中的具体内容有程序员安排。

存取效率的比较chars1[]="aaaaaaaaaaaaaaa";char*s2=

"bbbbbbbbbbbbbbbbb";aaaaaaaaaaa是在运行时刻赋值的;而

bbbbbbbbbbb是在编译时就确定的;但是,在以后的存取中,在栈上的数组比

指针所指向的字符串(例如堆)快。

比如:

#includevoidmain(){char

a=1;charc[]="90";char*p="90";a=c[1];a=

p[1];return;}对应的汇编代码10:

a=c[1];004010678A4DF1

movcl,byteptr[ebp-0Fh]0040106A884DFCmovbyteptr

[ebp-4],cl11:

a=p[1];0040106D8B55ECmovedx,dwordptr

[ebp-14h]004010708A4201moval,byteptr[edx+1]0040107388

45FCmovbyteptr[ebp-4],al第一种在读取时直接就把字符串中的元素读到

寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。

小结堆和栈的区别可以用如下的比喻来看出:

使用栈就象我们去饭

馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

windows进程中的内存结构在阅读本文之前,如

果你连是什么多不知道的话,请先阅读文章后面的。

接触过的人都知道,高级

语言都能通过变量名来访问内存中的数据。

那么这些变量在内存中是如何存放的呢?

程序又是如何使用这些变量的呢?

下面就会对此进行深入的讨论。

下文中的C

语言代码如没有特别声明,默认都使用VC编译的release版。

首先,来了解

一下C语言的变量是如何在内存分部的。

C语言有全局变量(Global)、本地变量

(Local),静态变量(Static)、寄存器变量(Regeister)。

每种变量都有不同的分配方式。

先来看下面这段代码:

#inelude<>intg仁0,g2=0,

g3=0;intmain(){staticints1=0,s2=0,s3=0;intv1=0,v2=0,

v3=0;7c7c6c3”2”1”0C0000000C4C0040100F894C83C43C0000003

C00401078C000C6A6A6A0000000C004068c1M.);7c7c6c

#include

#includeviomanip>

#include

usingnamespacestd;

intmain()

{

inta[2]={-1,1};

stringstr="*******************"・

inti=0,j=9,t=1;

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

{

j+=a[i<10];

if(i!

=0)t=t+a[i<10]*2;

cout<

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2