嵌入式软件笔试

来源:互联网 发布:网络机顶盒系统下载 编辑:程序博客网 时间:2024/04/30 01:52
/************************ 
    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;
    }
  }
f(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)
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++) {
   temp=given/pow(10,LEN-1-i);        // 从最高位开始
   given=given%((int) pow(10,LEN-1-i)); //int mustbe on both side of '%'
   str[i]=temp+'0';
 } 
 return str;
}
//-----
int main(void)
{
     printf("%s\n",int_to_string(9876));
     return 0;
}
/*------  E  -----*/
8. C语言实现插入排序算法(从大到小,从小到大).  
#include<stdio.h>
#define LEN 5
int a[LEN]={7,4,8,4,5};
void insertion_sort(void)
{
   int i,j,key;
   for(j=1;j<LEN;j++){
       printf("%d,%d,%d,%d,%d\n",a[0],a[1],a[2],a[3],a[4]);
       key=a[j];
       i=j-1;
       while( (i>=0) && (a[i]>key) ){                       // a[i]>key 从小到大; a[i]<key 从大到小
         a[i+1]=a[i];
         i--;
        }
       a[i+1]=key;
    }
  printf("%d,%d,%d,%d,%d\n",a[0],a[1],a[2],a[3],a[4]);
}


//-----
int main(void)
{
  insertion_sort();
   return 0;
}
/*------      E     -------*/
   9. C语言实现冒泡排序算法(从大到小,从小到大)
#include<stdio.h>
#define LEN 5
int a[LEN]={5,4,3,2,1};
void bubble_sort(void)
{
  int i,j,flag=1;
  int temp;
  for(i=1;(i<LEN)&&(flag==1);i++){
    flag=0;
    for(j=0;j<LEN-i;j++)  {
      if( a[j]>a[j+1] ){                              // a[j]>a[j+1]从小到大;a[j]<a[j+1] 从大到小
       flag=1;
       temp=a[j]; 
       a[j]=a[j+1];
       a[j+1]=temp;
       } 
    }
    printf("%d,%d,%d,%d,%d\n",a[0],a[1],a[2],a[3],a[4]);
  }
}
//--------
 int main(void)
{
  bubble_sort();
  return 0;
}
/*----   E   ----*/


 10. 在一个字符串中找一个字符串




 11. 计算一个数的阶乘
递归实现:
int factorial(int n)

   if (n == 0) 
      return 1; 
   else {
     int recurse = factorial(n-1); 
     int result = n * recurse; 
    return result; 
  }
}


循环实现:
int factorial(int n)
{
   int result = 1;
   while (n > 0) { 
 result = result * n;
 n = n - 1; 
   } 
  return result;
 }




12.用嵌套循环求1-100的素数
#include <stdio.h>
int main(void)
{
  int i, j; 
  for (i = 1; i <= 100; i++) {
for (j = 2; j < i; j++) 
 if (i % j == 0)
     break; 
   if (j == i) 
 printf("%d\n", i); 
 } 
 return 0;
}
/*------------    E   -------------*/










13. 打印菱形图案
void Damond(int L, char ch){ int n, j, k, i; for(n=1;n<=L/2+1;n++)    
 {        
  for(j=0;j<L/2+1-n;j++)          
    printf(" ");       
  for(k=1;k<=2*n-1;k++)          
    printf("%c", ch);      
  printf("\n");     
  }  
 
 for(i=L-n+1;i>=1;i--)   
  {      
   for(j=0;j<n-i-1;j++)            
     printf(" ");      
   for(k=1;k<=2*i-1;k++)         
    printf("%c", ch);      
  printf("\n");   
   }

/*----------    E   --------*/
14. 删除一个字符串中的指定字符。
#include <stdio.h>
void del_char(char *p, char ch)
{
  char *pch;
   while (*p != '\0') {
    if (*p == ch) {
      for (pch = p; *pch != '\0'; pch++)
        *pch = *(pch+1);
    }
   else
    p++;    
  }   



int main(void)
{
  char ch;
  char a[] = "hello world";
  scanf("%c", &ch);  
  
  del_char(a, ch);
  printf("%s\n", a);
}


/*-- E --*/
15. 统计一个字符串中子字符串的个数
#include <stdio.h>
#include <string.h>
int main(void)
{
  int i, j, k;
  int num = 0; 
  int len1, len2;
  char str1[80], str2[10];
  scanf("%s", str1);
  scanf("%s", str2);
 
  len1 = strlen(str1);    
  len2 = strlen(str2) - 1;    
 
   for (i = 0; i < len1 - len2; i++) {
    for (j = 0, k = i; str2[j] == str1[k]; k++, j++) 
    {
      if (j == len2)
        num++;
    }
   }
  printf("%d\n", num);

/*----- E -----*/






/************************ 
      Chapter3  系统类   
***********************/
1. Rtx51 Tiny是如何实现任务调度,切换的?
  时间片轮转,每个任务执行一定的时间退出执行下个任务如此循环。一个时间片内任务可以通过调用系统函数结束自身的执行转去执行下个任务。任务执行超过一个时间片系统强制终止该任务的执行转去执行下个任务。


2. Small Rtos51是如何实现任务调度,切换的?
  完全基于有优先级的抢占式操作系统。任务切换有两种情况:1当前任务自己放弃cpu时间; 2中断程序使优先级更高的任务就绪,所有中断退出后进行任务切换。


3. Uc/os是如何实现任务调度,切换的?
  完全基于有优先级的抢占式操作系统。任务切换有两种情况:1当前任务自己放弃cpu时间; 2中断程序使优先级更高的任务就绪,所有中断退出后进行任务切换。任务切换的过程大致是当前任务上下文入栈,最高优先级任务上下文出栈。
 




4.Linux是如何实现任务调度的?
  Linux既有时间片又有高优先级抢占。时间片到强制任务调度。时间片内有更高优先级任务就绪任务切换。


2. Bootloader移植过程要注意的事项,要做哪些工作
3. Emacs用过没有?
 用过
0 0