嵌入式软件类笔试面试小结

上传人:飞*** 文档编号:16690277 上传时间:2017-11-08 格式:DOCX 页数:16 大小:1.29MB
返回 下载 相关 举报
嵌入式软件类笔试面试小结_第1页
第1页 / 共16页
嵌入式软件类笔试面试小结_第2页
第2页 / 共16页
嵌入式软件类笔试面试小结_第3页
第3页 / 共16页
嵌入式软件类笔试面试小结_第4页
第4页 / 共16页
嵌入式软件类笔试面试小结_第5页
第5页 / 共16页
点击查看更多>>
资源描述

《嵌入式软件类笔试面试小结》由会员分享,可在线阅读,更多相关《嵌入式软件类笔试面试小结(16页珍藏版)》请在金锄头文库上搜索。

1、1最近忙于找工作,笔试面试了一些公司,本人主要找工作的方向是:嵌入式软件工程师。所以,针对嵌入式软件开发岗位的多次笔试与面试经历总结了一些常考查的知识点,希望有利于学弟、学妹们找工作。C 语言首先,对 C 的考查是必须的。既然打算从事嵌入式软件开发岗位,C 语言是基础,关于 C 主要需要把 C 语言三剑客即C 陷阱与缺陷 C 和指针 C 专家编程 ,还有C 语言深度剖析 。其中C 和指针 、 C 语言深度剖析这两本书至少看 2,3 遍,从此对于 C语言的基础考查,就很难难倒你了,没有捷径这几本书必须看的。1 关键字考查volatile:防止编译器优化 这个关键字是为了告诉你请不要做没谱的优化,

2、这个值可能变掉。 (笔试中考查过)volatile 使用的几个例子 并行设备的硬件寄存器(如:状态寄存器) 一个中断服务子程序中会访问到的非自动变量 多线程应用中被几个任务共享的变量一个指针可以是 volatile 吗可以,因为指针和普通变量一样,有时也有变化程序的不可控性。常见例:子中断服务子程序修改一个指向一个 buffer 的指针时,必须用 volatile 来修饰这个指针。说明:指针是一种普通的变量,从访问上没有什么不同于其他变量的特性。其保存的数组是个整形数据,和整形变量不同的是,这个整形数据指向的是一段内存地址。const:修饰的只读变量(笔试中考查过)const:这个关键字是告诉

3、你:请作为常量使用,而并非放心吧,那肯定是常量const int *p; /p 可变,p 指向的对象不可变int const *p; / p 可变,p 指向的对象不可变int * const p; /p 不可变,p 指向的对象可变const int * const p;/指针 p 和 p 指向的对象都不可变记忆方法说明:先忽略类型名(编译器解析的时候也是忽略类型名) ,我们看 const 离哪个近, “近水楼台先得月” ,离谁近就修饰谁。const int *p; /const 修饰*p,p 是指针,*p 是指针指向的对象,不可变int const *p; / const 修饰 *p,p 是指

4、针,*p 是指针指向的对象,不可变int * const p; /const 修饰 p,p 不可变,p 指向的对象可变const int * const p;/前一个 const 修饰*p, 后一个 const 修饰 p,指针 p 和 p 指向的对象/都可不变int const a = 12;const 修饰的 a 值是不是一定无法改变呢?非也,int *p = &a; *p = 5; 通过这两步,即可改变 a 的值,此时 a 值为 5.typedef 与 define(笔试中考查过)2把 typedef 看成是一种彻底的“封装”类型-在声明它之后不能再往里面增加别的东西。可以用其他类型说明符

5、对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做。#define peach intunsigned peach i;/*没问题*/typedef int banana;unsigned banana i;/*错误!非法*/面试题:typedef 和 define 有什么区别: 用法不同:typedef 用来定义一种数据类型的别名,增强程序的可读性。define 主要用来定义常量,以及书写复杂使用频率的宏。 执行时间不同:typedef 是编译过程的一部分,有类型检查的功能。define 是宏定义,是预编译的部分,其发生在编译之前,只是简单的进行字符串的替换,不进行类型的检

6、查。 作用域不同:typedef 有作用域限制。define 不受作用域约束,只要是在 define 声明后面的引用都是正确的。 对指针的操作不同:typedef 和 define 定义的指针时有很大的区别。注意:typedef 定义是语句,因此句尾要加上分号。而 define 不是语句,千万不能在句尾加分号。说明: #define PINT int *PINT a,b; / 定义结果是 a 的类型是 int *, b 的类型是 int typedef int * PINT;PINT a,b; /a,b 都为 int * 类型static:是常考查的关键字,笔试面试中考查次数相当多(笔试面试都

7、有考查过)static 修饰的局部变量存储于静态区,存储于静态区的变量有默认初始值为 0,这种变量在程序执行之前创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。普通变量存储于栈中,没有默认初始值。变量的链接属性和作用域不受影响,与普通局部变量一样。static 修饰函数,使得函数成为静态函数。指函数的作用域仅局限于本文件(所以又称内部函数) 。sizeof 和 strlen 的区别(他们的使用也是考查的重点)sizeof 和 strlen 有以下区别:sizeof 是一个操作符,strlen 是库函数。sizeof 的参数可以是数据的类型,也可以

8、是变量,而 strlen 只能以结尾为 0的字符串作参数。编译器在编译时就计算出了 sizeof 的结果。而 strlen 函数必须在运行时才能计算出来。并且 sizeof 计算的是数据类型占内存的大小,而 strlen 计算的是字符串实际的长度。数组做 sizeof 的参数不退化,传递给 strlen 就退化为指针了。sizeof(a = b+1)-并没有向 a 赋值,返回 a 的长度大小,并非 b 的3union 共用体(笔试考查过)union 维护足够的空间来置放多个数据成员中的“一种” ,而不是为每一个数据成员配置空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中

9、一个数据成员,所有的数据成员具有相同的起始地址。对这个关键字的考查,经常会考到判断大小端。变量 i 占 4 个字节,但只有一个字节的值为 1,另外三个字节的值都为 0。如果取出低地址上的值为 0,毫无疑问,这是大端模式;如果取出低地址上的值为 1,毫无疑问,这是小端模式。既然如此,我们完全可以利用 union 类型数据的特点:所有成员的起始地址一致。 (这个函数笔试考查过,需要记住)int checkSystem()union checkint i;char ch;c;c.i = 1;return(c.ch = 1);auto,好多人都没有见过这个关键字,但是有些选择题目中可能会有涉及。aut

10、o:在缺省情况下,编译器默认所有变量都是 auto 的。 (笔试选择题中出现过,要知道它是 C 语言的关键字)还有其他关键字就不一一列举了,书中都有详细介绍,我把常考到的简单说一些。2、关于 C 的其他常考查知识点设置地址为 0x67a9 的整型变量的值为 0xaa66(笔试中考查过)int *ptr;ptr = (int *)0x67a9;*ptr = 0xaa66;说明:这道题就是强制类型转换的典型例子,无论在什么平台地址长度和整型数据的长度是一样的,即一个整型数据可以强制转换成地址指针类型,只要有意义即可。方法二: int *(int *)0x67a9 = 0xaa66;不使用库函数写出

11、 strcpy strcat strcmp strlen strstr memset memcpy 这些函数的实现。或者直接考查,或者间接考查。首先要明白这几个函数如何使用,然后需要自己写出实现方式。我遇到过编写函数实现 strcpy 、strlen 的直接考查。对 strstr 的使用以及4函数实现的编写。strcpy 、strcmp、strlen 编写程序多次使用到。 memset memcpy 选择填空中遇到过。 (笔试中考查过)链表和数组有什么区别(面试中考查过)数组和链表有以下几点不同:(1 )存储形式:数组是一块连续的空间,声明时就要确定长度。链表是一块可不连续的动态空间,长度可变

12、,每个结点要保存相邻结点指针。(2 )数据查找:数组的线性查找速度快,查找操作直接使用偏移地址。链表需要按顺序检索结点,效率低。(3 )数据插入或删除:链表可以快速插入和删除结点,而数组则可能需要大量数据移动。(4 )越界问题:链表不存在越界问题,数组有越界问题。说明:在选择数组或链表数据结构时,一定要根据实际需要进行选择。数组便于查询,链表便于插入删除。数组节省空间但是长度固定,链表虽然变长但是占了更多的存储空间。关于布尔值(笔试中考查过,要知道 C 中无布尔值)布尔值只有 0 和 1C 并不具备显试的布尔类型,所以使用整数来代替。其规则是:零的假,任何非零值皆为真。短路求值& |(在线笔试

13、中有涉及)&操作符的左操作数总是首先进行求值,如果它的值为真,然后就紧接着对右操作数求值。如果操作数的值为假,那么右操作数便不再进行求值,因为整个表达式的值肯定是假的。|操作数也是同理。当左操作数的值为真,右操作数便不再求值。a0与 a(这个是必须弄清楚的,多次考查过)int a5;a0是一个元素,a 是整个数组。sizeof(a) = 20; sizeof(&a0) = 4;/取元素 a0的首地址sizeof(&a) = 4; /取数组 a 的首地址,在 VC+6.0 为 20,Bug数组名的类型是“指向 int 的常量指针”a 是数组首元素的首地址,也就是 a0的首地址&a0表示数组首元素

14、的地址;&a 表示数组的首地址看法:在表示地址时:a 与&a0含义用法是一致的a 作为右值时其意义与&a0是一样,代表的是数组首元素的首地址,而不是数组的首地址(用在表达式 sizeof(a)中时, a 表示的数组名,此时 a 并没有被用作右值) 。但是注意,这仅仅是代表,并没有一个地方(这只是简单的这么认为,其具体实现细节不作过多讨论)5来存储这个地址,也就是说编译器并没有为数组 a 分配一块内存来存其地址,这一点就与指针有很大的差别。a 不能作为左值!main()int a5=1,2,3,4,5;int *ptr=(int *)(&a+1);printf(%dn%dn,*(a+1),*(p

15、tr-1);/此处把 a 换成&a0也是可以的&a + 1-取数组 a 的首地址,该地址的值加上 sizeof(a) 的值,即&a + 5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。(int *)(&a+1)-则是把上一步计算出来的地址,强制转换为 int * 类型,赋值给 ptr。*(a+1)- a,&a 的值是一样的,但意思不一样,a 是数组首元素的首地址,也就是 a0的首地址,&a 是数组的首地址,a+1 是数组下一元素的首地址,即 a1的首地址,&a+1 是下一个数组的首地址。所以输出 2*(ptr-1)-因为 ptr 是指向 a5,并且 pt

16、r 是 int * 类型,所以*(ptr-1)是指向 a4,输出 5。大端存储与小端存储(笔试中考查过)小端: 较高 的有效字节存放在较高 的的存储器地址,较低 的有效字节存放在较低 的存储器地址。 大端: 较高 的有效字节存放在较低 的存储器地址,较低 的有效字节存放在较高 的存储器地址。我们常用的 X86 结构是小端模式,而 KEIL-C51 则为大端模式。很多的 ARM,DSP 都为小端模式。有些 ARM 处理器还可以由硬件来选择是大端模式还是小端模式。内存对齐(常考查知识点)字,双字,和四字在自然边界上不需要在内存中对齐。 (对字,双字,和四字来说,自然边界分别是偶数地址,可以被 4 整除的地址,和可以被 8 整除的地址。 )无论如何

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号