嵌入式软件工程师应聘面试题第一篇

近日,我混迹于深圳各个区的大小街巷,龙华、福田、南山、宝安,各个区都有自己的特色,我也接到了各大公司的面试邀请,参加了各种公司的面试、笔试,现在有空,安静下来,进行复习、分析、实践,只为把关键的技术点把握。。。。。

1、给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3,在以上两个操作中, 要保持其它位不变。

char a=0x00;//char 1字节 8位,int 4字节 32位,a为  0000 0000 
#define bit3 (0x1<<3)  //0x1为0001,左移三位后为1000,0x8
a |= bit3; // 0|1=1,1|1=1,0|0=0,a或bit3后第四位和1或,第四位为1,其他位和0或,保持不变,此时a为 0000 1000,实现设置bit3
a &= ~bit3;//0&0=0,0&1=0,1&1=1,a为 0000 1000,~bit3为 1111 0111 ,运算后a为 0000 0000,实现清除bit3

2、用变量a给出下面的定义
a) 一个整型数(An integer) int a;
b) 一个指向整型数的指针(A pointer to an integer) int *a;
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer) int **a;
d) 一个有10个整型数的数组(An array of 10 integers) int a[10];
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers) int *a[10];
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers) int (*a)[10];
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer) int (*a)(int);
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer ) int (*a[10])(int);

3、嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。

int *ptr;
ptr = (int *)0x67a9;//设置地址为0x67a9
*ptr = 0xaa66; //设置目标为0xaa66
*(int *const)(0x67a9)=0xaa66;//这是比较难把握的,尽量用上面的

4、写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
为了尽量避免边际效应,宏定义时常要注意括号的使用。什么是边际效应呢?我举个例子:
#define FUN(A,B) A*3+B*5
输入A=1+3;B=2+3;很明显你想要的是4*3+6*5=42;但是结果却是1+3*3+2+3*5=1+9+2+15=27;这个结果并不是我们想要的。这个现象就是我这里说的边际效应。所以宏的参数要用括号括起来当成整体输入。

#define MIN(A,B) ((A)<(B)?(A):(B))   //宏定义一般都用大写字母,用来区分正常的逻辑代码  在宏中把参数用括号括起来
#define MIN(A,B) (((A)<(B))?(A):(B))  //也可以

5、交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3。
算术算法:

a=3;b=5;
a=a+b;//a=8,b=5
b=a-b;//a=8,b=3
a=a-b;//a=5,b=3

位操作算法,异或:

a=3;//0011
b=5;//0101
/****第一种****/
a=a^b;//a=0011^0101=0110;a=6;
b=a^b;//b=0110^0101=0011;b=3;
a=a^b;//a=0110^0011=0101;a=5;
/****第二种****/
b=a^b;//b=0011^0101=0110;b=6;
a=a^b;//a=0011^0110=0101;a=5;
b=a^b;//b=0101^0110=0011;b=3;

6、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define ONE_YEARS_SECONDS (365UL*24UL*60UL*60UL) //(365*24*60*60)UL 会报错 可能编译器的原因
#define ONE_YEARS_SECONDS ((unsigned long)(365*24*60*60))
UL:unsigned long int 无符号长整型
这些都是对于16位机的,电脑的32位和64位,可以不用加UL,也不会溢出

7、嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
⑴while(1){} ⑵for( ; ; ) ⑶loop: … goto loop;

8、评价下面的代码片断:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;

答:对于16位机可以这样写;如果是int型不是16位的计算机来说,上面的0xffff就错了,最佳的写法为:unsigned int compzero = ~0; 这适用于任何位机。

9、已知一个数组table,用一个宏定义,求出数组的元素个数
sizeof函数的作用:关键字 sizeof 是一个单目运算符,而不是一个函数。用于计算目标的字节数的。sizeof操作符以字节形式给出了其操作数的存储大小。 操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。
int table[10];//或者 char table[10];
#define tab_num (sizeof(table)/sizeof(table[0]))
sizeof table :求的是数组的字节数,int类型为4字节,一共10个,所以整个数组的字节数为40
sizeof table[0]:求的是数组第一个的字节数所以为4,相除就得出数组的个数为10;
sizeof(char)=1; sizeof(char *)=4; sizeof(int)=4; sizeof(short)=2; sizeof(long)=4; sizeof(float)=4; sizeof(double)=8; sizeof(long double)=12;
sizeof(“abcd”)=5;//自动转成字符型数组,即char a[5]={“abcd”};这里字符串后面有个结束符’\0’,所以结果为5.

10、C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;

答:是合法的,这里的a+++b可以拆分为a++ +b,这里涉及到运算符优先级问题,++的优先级高于+,所以编译器在预编译的时候会把先遇到的++看成一个运算符;我上机操作并进行了验证:首先是原式可以正常输出,然后我尝试了c=a+++++b;然后就报错了,error: lvalue required as increment operand,作为递增操作数所需的有效值;也就是说++缺失了操作对象,可见编译器把a+++++b拆分为了a++ ++ +b,所以++没有可以进行自增的对象,所以报错。这也证明了前面的++优先级高+,所以这里连续遇到了两个++,就报错了。然后我把+++++改成了++-++,这里编译就通过了,而且结果也在意料之中。换成+++--也一样可以。所以这里是优先级的问题,这是合法的表达式。我也看了很多人对这个问题的解释,都说是看编译器心情,按最优处理原则去处理,什么是最优处理原则?他给出的解释是编译器应当能处理尽可能所有合法的用法,也就是说把代码尽可能的避免非法的编译?也就是说编译器是有思想的?拿+++++来看,如果按照他们所谓的最优处理,这个可以被编译器处理为++ + ++,然而却没有。

11、int main(void)
{
unsigned int a = 6;
int b = -20;
char c;
(a+b>6)?(c=1):(c=0);
}

答:这个程序我们可以先猜想一下输出结果,由题目得知a+b=-14,-14<6,所以输出为c=0。上机后发现结果相反,c=1,a+b=-14。a+b明明为-14,为啥比6大呢?为了解决这个问题,我查了计算机的加法方式,它是把所有加数转成补码再进行相加,结果再进行补码就是原结果。我也查了一些资料,在C语言中,进行混合运算时,编译系统遵循一定规则,完成数据类型的自动转换,即隐式类型转换。一般是占用内存字节数少类型,向占用内存字节数多的类型进行转换,以防止精度丢失。一般来说,signed类型会被转成unsigned类型。我总结公式为:unsigned类型最大值+1+(signed类型的值)。比如这里的-14,转成unsigned类型,代入公式有 2^32-1+1+(-14),这个值远大于6。所以c=1。

12、C语言的关键字
在这里插入图片描述
(1)声明类型(17):
void、char、short、int、long、float、double、signed、unsigned、struct、union、enum、auto、static、extern、register、const
(2)循环类型(5):
for、do、while、break、continue
(3)条件类型(6):
if、else、switch、case、default、goto
(4)其他类型(4):
sizeof、typedef、volatile、return

13、a=b*2;a=b/4;a=b%8;a=b/8*8+b%4;a=b*15;效率最高的算法
计算机的本质是对寄存器的操作,运算过程其实就是对寄存器的操作。所以高效的方法是直接操作寄存器,即位操作。
a=b*2 <===> a=(b<<1)
a=b/4 <===> a=(b>>2)
a=b%8 <===> a=b&7
a=b/8*8+b%4 <===> a=((b>>3)<<3)+(b&3)
a=b*15 <===> a=(b<<4)-b

14、关键字const有什么含意?作用是什么?
const是一个修饰符,用于声明只读变量。被修饰的变量只有读权限,没有写权限。所以被const修饰过的变量为常量。
int a;//a可读可写
const int a; //整形变量a只读
const int *a;//*a只读,a可读可写
int *const a;//*a可读可写,a地址可读不可写
const int const a;//a地址和a都是只读

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☆程序小黑★

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值