嵌⼊式软件⼯程师⾯试遇到的经典题⽬
嵌⼊式软件⼯程师⾯试遇到的经典题⽬
1、错误
char* s1="hello";
char* s2="world";
char* s3=strcat(s1,s2);
这样做对吗,如果不对请说明原因。
解答:
不对,s1与s2都为常量指针,其内容不可修改,运⾏就会产⽣段错误。
下⾯的代码有何问题?
void test1()
{
 char string[10];
 char* str1 ="0123456789";
 strcpy( string, str1 );
}
字符串strl的末尾是以’ \0 ’结尾的,所以他的长度是11,⽽string的长度不够。。。。
但是我⾃⼰写了这样的程序,他是可以拷贝的。。。。
2、下⾯的代码输出是什么,为什么?
void foo(void)
{
unsigned int a=6;
int b=-20;
(a+b>6)?puts(">6"):puts("<6")
}
输出“>6”,应为⽆符号数和有符号相加,有符号的整形数会转化成⼀个⽆符号的整型数,⽽且负的有符号整型数转换后会变得⾮常⼤,所以相加会⼤于6。
3、C语⾔编译时动态链接和静态链接得区别是什么?
动态库:
1、链接时不复制,程序运⾏时由系统动态加载到内存,供程序调⽤,系统只加载⼀次,多个程序可以共⽤,节省内存。
2、程序升级简单,因为app⾥⾯没有库的源代码,升级之后只要库的名字不变,函数名以及参数不变,只是实现做了优化,就能加载成功。
3、. 加载速度⽐静态库慢
4、发布程序需要提供依赖的动态库
静态库:
1、静态库被打包到程序中加载速度快
2 、发布程序⽆需提供静态库,应为已经在app中,移植⽅便
3 、 链接时完整的拷贝⾄可执⾏⽂件中,被多次使⽤就会有多次冗余拷贝
4、 更新,部署,发布⿇烦
4、C语⾔关键字static得作⽤是什么?
①隐藏作⽤, 可以在不同的⽂件中定义同名变量和同名函数。
②对于变量来说, 保持变量持久, 静态数据区的变量会在程序刚刚运⾏时就完成
初始化, 也是唯⼀⼀次初始化; 储存在静态数据区, 静态存储区只有两种变量(全
局变量和 static 静态变量) 。
③默认初始化为 0x00,和全局变量⼀样的属性, 减少程序员的⼯作量。
5、分别说明⼀下三个变量声明得含义:
int const*p;
int*const p;
int const*p const;
int const*p=const int *p; const修饰的是指针 p,表⽰指针p的值不能改变,⽽p(即地址)是可以改变的;
int * const p; const修饰的是p(即地址)是常量,不可改变,但是*p的值可以改变。
int const *p const ; 上⾯两种情况兼得,表⽰只读,其地址以及地址中的值都不可改变
6、简述TCP/IP镞包含哪些分段,每⼀层有哪些常⽤协议?
应⽤层:http dns telnet ftp TFTP 。。。。
传输层:tcp udp
⽹络层:ip ICMP ARP rarp
数据链路层:ethnet ethnet2 802.3 ppp fr x.25 hdlc
物理层:⽐特流
7、从在浏览器地址栏中输⼊www.baidu到看到百度⾸页,这个过程中间经历了什么?都涉及到哪些⽹络协议?
按照时间顺序:
1.客户端浏览器获取⽤户在地址栏输⼊的域名。
2.客户端浏览器将域名发送给DNS域名系统,请求解析。
3.DNS解析域名得到相应的IP,返回给客户端浏览器。
4.客户端浏览器根据IP向服务器发起TCP三次握⼿,建⽴TCP连接。
5.客户端浏览器向服务器发送HTTP请求,请求百度⾸页。
6.服务器通过HTTP响应向客户端浏览器返回百度⾸页⽂件。
7.释放TCP连接。
8.客户端浏览器解析HTML⽂件,根据⽂件内容获取CSS、JS等资源⽂件,将页⾯渲染展⽰给⽤户。
TCP/IP五层模型中⽹络层及以上⽤到的协议:
1.应⽤层:HTTP、DNS、HTTPS
2.传输层:TCP、UDP
3.⽹络层:IP、ARP
8、编写strcat函数
2.strcat函数原型
char*my_strcat(char*dest,const char*src)//将源字符串加const,表明其为输⼊参数
{
  char*strDest=dest;
  assert(dest!=NULL&& src!=NULL);//对源地址和⽬的地址加⾮0断⾔
  //若使⽤while(*Dest++),则会出错,指向'\0'之后,会出现dest++,则指向了个'\0'的下⼀个位置,
  while(*dest !='\0')
  {
    dest++;//循环体内的++可以使指向字符串结束标志'\0'
  }
  while((*dest++=*src++)!='\0');
  return strDest;
}
之后会问为什么要char *的返回值:
主要是为了实现链式表达式。
如 strcpy(buf, strcat(dest, src) );
9、使⽤C语⾔中的#define来定义⼀个常量来表⽰⼀年有多少秒?#define SECONDS_PER_YEAR (606024*365)UL
⼀定要加括号,宏定义只是替换,不加括号会出错。。。。
10、实现把字符串转化成整数
int my_atoi(char*str)
{
int sum=0,status=1;
if(str ==NULL)
{
return0;
}
if(*str =='-')
{
status =-1;
str++;
}
while((*str)!='\0')
{
sum=sum*10+((*str)-'0');
str++;
}
return sum*status;
}
11、写⼀个程序验证系统的⼤⼩端存储格式
/*⽅法1*/
typedef union{
int i;
char c;
}my_union;
int checkSystem1(void)
{
my_union u;
u.i =1;
return(u.i == u.c);
}
/*⽅法2*/
int checkSystem2(void)
{
int i =0x12345678;
char*c =&i;
return((c[0]==0x78)&&(c[1]==0x56)&&(c[2]==0x34)&&(c[3]==0x12));
}
12、如何判断⼀个byte数据中有多少bit为1?
int select(unsigned char data)
{
int count=0,i=1;
while(data!=0)
{
count +=(data & i);
data >>=1;
}
return count;
}c语言编译器app怎么用
13、 C语⾔中关键字volatile的含义
volatile 的意思是“易失的,易改变的”。这个限定词的含义是向编译器指明变量的内容可能会由于其他程序的修改⽽变化。
⼀个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在⽤到这个变量时必须每次都⼩⼼地重新读取这个变量的值,⽽不是使⽤保存在寄存器⾥的备份
⼀般说来,volatile⽤在如下的⼏个地⽅:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
⼀个参数既可以是const还可以是volatile吗?解释为什么。
是的。⼀个例⼦是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
14、进程间通信的⽅式有哪些?
1.⽆名管道( pipe ): 管道是⼀种半双⼯的通信⽅式,数据只能单向流动,⽽且只能在具有亲缘关系的进程间使⽤。进程的亲缘关系通常是指⽗⼦进程关系。
2.有名管道 (named pipe) : 有名管道也是半双⼯的通信⽅式,但是它允许⽆亲缘关系进程间的通信。
3.消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载⽆格式字节流以及缓冲区⼤⼩受限等缺点。
4.信号量( semophore ) : 信号量是⼀个计数器,可以⽤来控制多个进程对共享资源的访问。它常作为⼀种锁机制,防⽌某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同⼀进程内不同线程之间的同步⼿段。
5.信号 ( sinal ) : 信号是⼀种⽐较复杂的通信⽅式,⽤于通知接收进程某个事件已经发⽣。
6.共享内存( shared memory ) : 共享内存就是映射⼀段能被其他进程所访问的内存,这段共享内存由⼀个进程创建,但多个进程都可以访问。共享内存是最快的 IPC ⽅式,它是针对其他进程间通信⽅式运⾏效率低⽽专门设计的。它往往与其他通信机制,如信号两,配合使⽤,来实现进程间的同步和通信。
7.套接字( socket ) : 套解字也是⼀种进程间通信机制,与其他通信机制不同的是,它可⽤于不同机器间的进程通信。
15、堆和栈的区别
①、申请⽅式不同:栈由系统⾃动分配,堆是由⼈为⾃⾏开辟(malloc,new)
② 、申请的⼤⼩不同:栈是从⾼地址像低地址分配的,分配空间较⼩,堆是由地址向⾼地分配的,空间较⼤
③ 、申请效率不同:栈由系统分配,分配速度较快,堆⼀般较慢
④ 、栈是连续的地址空间,堆不是连续的地址空间,很容易产⽣内存碎⽚,浪费内存。
16、分别给出bool,int,float,指针变量与“零值”⽐较的 if 语句(假设变量名为var)
Bool:if(!var)
Int :if(var==0)
Float:const float val=0.00000001
If((var >=-val)&&(var <= val))
17、进程和线程的区别
进程和线程的根本区别是进程是操作系统资源分配的基本单位,⽽线程是处理器任务调度和执⾏的基本单位。另外区别还有资源开销、包含关系、内存分配、影响关系、执⾏过程等。
资源开销:每个进程都有独⽴的代码和数据空间(程序上下⽂),程序之间的切换会有较⼤的开销;线程可以看做轻量级的进程,同⼀类线程共享代码和数据空间,每个线程都有⾃⼰独⽴的运⾏栈和程序计数器(PC),线程之间切换的开销⼩。
包含关系:如果⼀个进程内有多个线程,则执⾏过程不是⼀条线的,⽽是多条线(线程)共同完成的;线程是进程的⼀部分,所以线程也被称为轻权进程或者轻量级进程。
内存分配:同⼀进程的线程共享本进程的地址空间和资源,⽽进程之间的地址空间和资源是相互独⽴的。
影响关系:⼀个进程崩溃后,在保护模式下不会对其他进程产⽣影响,但是⼀个线程崩溃整个进程都死掉。所以多进程要⽐多线程健壮。
执⾏过程:每个独⽴的进程有程序运⾏的⼊⼝、顺序执⾏序列和程序出⼝。但是线程不能独⽴执⾏,必须依存在应⽤程序中,由应⽤程序提供多个线程执⾏控制,两者均可并发执⾏。
进程和线程的根本区别是进程是操作系统资源分配的基本单位,⽽线程是处理器任务调度和执⾏的基本单位
18.写⼀个“标准”宏MIN,这个宏输⼊两个参数并返回较⼩的⼀个。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。