精选嵌入式软件开发面试笔试题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
嵌入式软件笔试
/************************
Chapter1 语法类
***********************/
1 .volatile作用?应用场合举3例
volatile修饰的变量表示这个变量可能会被意想不到的改变,对该变量的操作将不作优化,用到该变量时都从这个变量的原始地址读取,而不是用保存在寄存器里的备份。
Volatile常用在:
1). 硬件寄存器(如:状态寄存器)。
2). 中断程序中会访问到的非自动变量(Non-automatic variables)。
3). 多线程应用中几个任务共享的变量
2. 一个参数既可以是const还可以是volatile吗?解释为什么。
是的。比如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
3. 一个指针可以是volatile 吗?解释为什么。
是的。 比如一个中断服务子程序修该一个指向一个buffer的指针时。
4. 用变量a给出下面的定义
a) 一个整型数
b) 一个指向整型数的指针
c) 一个指向指针的指针,它指向的指针是指向一个整型数
d) 一个有10个整型数的数组
e) 一个有10个指针的数组,该指针是指向一个整型数的
f) 一个指向有10个整型数数组的指针
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *(a[10]); // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument
and returns an integer
h) int (*a[10]) (int); // An array of 10 pointers to functions that take an in
teger argument and return an integer
5. 什么是存储机制里的大、小端模式?试举例说明
大端模式(big-edian):MSB存放在最低端的地址上。举例,双字节数0x1234以big-endian的方式存在起始地址0x00002000中:
| data |<-- address
| 0x12 |<-- 0x00002000
| 0x34 |<-- 0x00002001
在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):
bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
MSB----------------------------------LSB
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
= 0x8 B 8 A
小端模式(little-endian):LSB存放在最低端的地址上。举例,双字节数0x1234以little-endian的方式存在起始地址0x00002000中:
| data |<-- address
| 0x34 |<-- 0x00002000
| 0x12 |<-- 0x00002001
在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如
下(以双
字节数0x8B8A为例):
bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
MSB-----------------------------------LSB
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
= 0x8 B 8 A
6. 写一段用来判断内存存储方式是大端还是小段的代码。
联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。代码如下:
int checkCPUendian()
{
union
{
unsigned int a;
unsigned char b;
}c;
c.a = 1;
return (c.b = = 1);
}
/*return 1 : little-endian, return 0:big-endian*/
7. 定义一个返回值是指向函数的指针且有一个指向函数的指针作参数的函数。
通用形式如下:
typedef int (*P)( ); // 定义一个函数指针P类型
P function( int (*p)( ) ); // 定义一个函数返回值P类型,且定义一个指向函数的指针p作参数
8. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365) UL // UL怎么个用法?你暂不要加
9 . 写一个“标准”宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ( (A) <= (B) ? (A ): (B) )
10. 关键字static的作用是什么?
两个作用:
1) 局部变量被声明为static 则这一函数调用结束后该变量值保持不变。
2) 外部变量被声明为static表明它是一个本地全局变量。该变量只能在该文件内被访问,不能被其它文件访问。
11.关键字const有什么含意?
声明一个变量为只读。
12. 下面的声明都是什么意思?
1)const int a; 2)int const a; 3)const int *a; 4)int * const a; 5) int const * const a ;
1,2一样a为只读整形变量;3 指向一个只读整形变量的指针;4 指向整形的只读指针; 5 指向只读整形的只读指针。
13. C语言实现设置一绝对地址为0x1234的整型变量的值为0xaa55。
int *p;
p=(int *) 0x1234; // 把整型数0x1234强制转换(typecast)为一指针
*p=0xaa55;
14. 找出下面一段ISR的问题。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}
1)ISR不能传递参数。
2)ISR不能有返回值。
3)ISR应该短且有效率,在ISR中做浮点运算不明智。
15 .下面的代码输出是什么?为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
输出 > 6,原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。-20成了
一个非常大的正数。 // 此题的输出确实是这样,但单纯输出a+b时结果又是-14 很怪异 迷惑~~~~~~!
16. 评价下面的代码片断:
unsigned int
zero = 0;
unsigned int compzero = 0xFFFF;
如果碰巧int型是16位则上述代码没有问题,否则上面的代码不正确。应写成:unsigned int compzero = ~0;
17 . 下面代码执行后a,b,c的值各是多少?
int a = 5, b = 7, c;
c = a+++b; // c = (a++)+b
a = 6, b = 7, c = 12. // 吾已试,结果确如此
18. Typedef和#define的区别
#define在预编译的时候处理作机械的字符替换。Typedef在编译的时候处理,并不是作简单的字符替换。而是如同定义变量一样声明一个类型。然后用它去定义这种类型的变量。比如下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两句都是定义dPS 和 tPS 为一个指向结构s的指针。 typedef更好。比如:
dPS p1,p2;
tPS p3,p4;
第一句扩展为struct s * p1, p2;
这条代码定义p1为指向结构的指针,p2为一个实际的结构体。第二句定义p3 和p4 为指向结构体s的指针。
/************************
Chapter2 编程类
***********************/
1. 在字符串中找出所有与给定字符相同字符的位置。
#include <stdio.h>
char s[6]="hello";
void search_char(char given)
{
int i=0,j=0;
while(s[i]!='\0'){
if(s[i]==given){
printf("location = %d\n", i);
j++;
}
i++;
}
if(j==0)
printf("No %c found\n",given);
}
int main(void)
{
search_char('o');
return 0;
}
/*----- E ----*/
2. 将一个字符串自身逆序.
#include <stdio.h>
#define LEN 12
int main(void)
{
int m,i;
char temp;
char s[LEN]="hello tiger";
m=(LEN-1)/2;
printf("%s\n",s);
for(i=0;i<m;i++){
temp=s[i];
s[i]=s[LEN-2-i];
s[LEN-2-i]=temp;
}
printf("%s\n",s);
return 0;
}
/*------- E ------*/
3. 链表的基本操作及链表自身逆序。
/*---- chain operate from Data Structure ---*/
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node *next;
}SLNode;
//---- initiate
void ListInitiate(SLNode **head)
{
if( (*head=(SLNode *)malloc(sizeof(SLNode)))==NULL ) exit(1);
else printf("OK\n");
(*head)->next=NULL;
}
//---- length cal
int ListLength(SLNode *head)
{
SLNode *p=head;
int size=0;
while(p->next!=NULL){
p=p->next;
size++;
}
return size;
}
//----insert a node
int ListInsert(SLNode *head,int i,DataType x)
{
SLNode *p,*q;
int j;
p=head;
j=-1;
while( (p->next!=NULL) && (j<(i-1)) ) {
p=p->next;
j++;
}
if(j!=(i-1)) {
printf("Position error\n");
return 0;
}
if((q=(SLNode *)malloc(sizeof(SLNode)))==NULL)
exit(1);
q->data=x;
q->next=p->next;
p->next=q;
return 1;
}
//----delete a node
int ListDelete(SLNode *head,int i,DataType *x)
{
SLNode *p,*s;
int j;
p=head;
j=-1;
while((p->next!=NULL) && (p->next->next!=NULL) && (j<i-1) ){
p=p->next;
j++;
}
if(j!=i-1){
printf("Position error\n");
return 0;
}
s=p->next;
*x=s->data;
p->next=p->next->next;
free(s);
return 1;
}
//----- data get
int ListGet(SLNode *head,int i,DataType *x)
{
SLNode *p;
int j;
p=head;
j=-1;
while((p->next!=NULL)&&(j<i)) {
p=p->next;
j++;
}
if(j!=i) {
printf("Position error\n");
return 0;
}
*x=p->data;
return 1;
}
//----Destroy a chain
void Destroy(SLNode **head)
{
SLNode *p,*p1;
p=*head;
while(p!=NULL) {
p1=p;
p=p->next;
free(p1);
}
*head=NULL;
}
//-----converse a chain
void converse(SLNode *head)
{
SLNode *p,*q;
p=head->next;
head->next=NULL;
while(p!=NULL) {
q=p;
p=p->next;
q->next=head->next;
head->next=q;
}
}
//---- composite operation
int main(void)
{
SLNode *head;
int i,x;
ListInitiate(&head);
for(i=0;i<10;i++) {
if(ListInsert(head,i,i)==0){
printf("Error\n");
return 1;
}
}
if(ListDelete(head,0,&x)==0) // chain,position,data address
{
printf("Error\n");
return 1;
}
if(ListInsert(head,0,100)==0) {
printf("Error\n");
return 1;
}
converse(head);
for(i=0;i<ListLength(head);i++) {
if(ListGet(head,i,&x)==0) // chain,position,data address
{
printf("Error\n");
return 1;
}
else printf("%d ",x);
}
printf("\n");
Destroy(&head);
return 0;
}
/*------ E -------*/
4. 写一个二分查找算法。
#include <stdio.h>
#define size 10
int g[size]={0,1,2,3,4,5,6,7,8,9};
int search(int x)
{
int low=0;
int high=size-1;
int mid;
while(low<=high) {
mid=(low+high)/2;
if(g[mid]==x)
return mid;
else if(g[mid]<x)
low=mid+1;
else if(g[mid]>x)
high=mid-1;
}
return -1;
}
//----
int main(void)
{
printf("%d\n",search(7));
return 0;
}
/*--- E ---*/
5. 计算一个字节里(byte)里面有多少bit被置1.
#include <stdio.h>
int cal_bit(char a)
{
int i,j=0;
for(i=0;i<8;i++) {
if((a&0x01)==0x01)
j++;
a=a>>1;
}
return j;
}
//--
int main(void)
{
printf("%d\n",cal_bit(255));
return 0;
}
/*---- E ----*/
6. 字符串转换为整数,比如“1234”转换成1234.
#include <stdio.h>
char str[6]="12345";
int string_to_int(char s[])
{
int i;
int sum=0;
for(i=0;s[i]!='\0';i++)
sum=sum*10+s[i]-'0';
return sum;
}
//-----
int main(void)
{
printf("%d\n",string_to_int(str));
return 0;
}
/*------ E -----*/
7. 整数转换为字符串,比如1234转换成“1234”.
#include <stdio.h>
#include <math.h>
#define
LEN 4
char str[]=" ";
char *int_to_string(int given)
{
int i;
int temp;
for(i=0;i<LEN;i+