(笔记)英腾技术开发实习生面试技术题(答案分析)

来源:互联网 发布:什么是sql注入攻击 编辑:程序博客网 时间:2024/06/04 19:42

题目:

一、 选择题(4题)
1.Ethernet链接到Internet用到以下那个协议?
A.HDLC; B.ARP; C.UDP; D.TCP; E.ID
2.属于网络层协议的是:
A.TCP; B.IP; C.ICMP; D.X.25
3.Windows消息调度机制是:
A.指令队列; B.指令堆栈; C.消息队列; D.消息堆栈;
4.unsigned short hash(unsigned short key)
{
return (key>>4)%256;
}
请问hash(16),hash(256)的值分别是:
A.1.16; B.8.32; C.4.16; D.1.32

二、 简答题(10题)
1、 C语言局部变量能否和全局变量重名?

2、 s[10]的另外一种表达方式是什么?

3、 关键字static的作用是什么?

4、 对(-1.2345)取整是多少?

5、 设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。

6、 a+++++b所表示的是什么意思?有什么问题?

7、 下面的代码输出是什么,为什么?
void foo(void)
{ unsigned int a = 6;
int b = -20;
(a+b > 6) puts(“> 6”) : puts(“<= 6”);
}

8、中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断,并产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius) { double area = PI * radius * radius; printf(” Area = %f”, area); return area; }

9、 C语言的const的含义是什么。在定义常量时,为什么推荐使用const,而不是#define。

10、C语言的volatile的含义是什么。使用时会对编译器有什么暗示?

答案:
选择题(共4题)

题目 1 2 3 4 答案 D BC C A

简答题(共10题)
1:
能。
在C语言中:C语言中无法引用被隐藏的外部作用域对象,因为无法指定具体作用域。
在C++中:C++中要引用被隐藏的全局作用域对象,可以在对象的标识符前加上 :: 限定全局作用域。

①. 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。

//示例:#include <stdio.h>int val = 10;int get_val(){//int val = 6;return val;}int test(){int val = 5;get_val(); }int main(){    printf("%d\n",test());  /* 得到的是全局的val = 10 */                            //int val = 6; 使能,则得到 val = 6    return 0;}

//示例:
这里写图片描述

②.对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。

2:
数组和指针其实是数据存在形态的两种表现形式,如果说对于数组s[],我们知道s=s[0],那么s[10]的另一种表达方式就是:(s+10)。

3:
关键字static有三个明显的作用:
1). 修饰局部变量,一般局部变量是存放在栈区,且局部变量的生命周期在所在语句模块执行结束时便结束。 但是static修饰的后,局部变量存放在静态数据区,生命周期持续到整个程序运行结束为止。
static修饰的局部变量只在初次运行的时候进行初始化。
2). 修饰全局变量,全局变量它可以被同一个工程的其他源文件访问。但static修饰的后的全局变量,从整个工程可见变为源文件可见。它是一个本地的全局变量。
3). 修饰函数,用static修饰函数的话,和修饰全局变量大同小易,就是改变了函数的作用域。

4:
其实不同的取整函数可能有不同的结果,不过这个数没有太大的争议,答案是-1。

5:
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:

 int * ptr;   ptr = (int *)0x67a9;   *ptr = 0xaa55; 

一个较晦涩的方法是:

  *(int * const)(0x67a9) = 0xaa55;   //不能作为变量再次赋值

6:
这个东西(称之为东西一点都不过分)其实并没有语法错误,按照C对运算符等级的划分,++的优先级大于+,那么这句话会被编译器看做:(a++)+(++b),这回明白了吧。有什么问题,语法上没有问题,有的是道德上的问题!作为一个优秀的程序员,我们要力求语句的合法性和可读性,如果写这句的人是在一个team里,那么他基本会被打的半死……最后讨论一下结果:假设a之前的值是3,b是4,那么运行完这个变态语句后,a的值是4,b是5,语句的结果是8。

7:
这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。
不管如何,unsigned 是无符号数。 b 是有符号数负数,无符号数和有符号数混合运算 ,默认,把有符号数内容当成无符号数解释 计算。-20 就当 0xffffffec (4294967276).显然((a+b=0xfffffff2) > 6) 成立。输出 > 6。

#include <stdio.h>int main(){    unsigned int a = 6;     int b = -20;    (a+b > 6) ? puts("> 6") : puts("<= 6");     printf("\n");    printf("%x\n",(a+b));    printf("%d\n",(a+b));    return 0;}//结果://> 6//fffffff2//-14

这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

8:
这个函数有太多的错误了,以至让人不知从何说起了:
1). ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2). ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
3). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
4). 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

9:
我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。
ESP(Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么. 如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?

const int a;  // const a;int const a;  // const a;  const int * a;  //int * a; int const* a;  //int * a; int * const a;  //const a  int const * a const;   

前两个的作用是一样,a是一个常整型数。
第三,四意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第五意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?

我也如下的几下理由:
1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

10:
volatile的本意是“易变的”。 由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化,但有可能会读脏数据。
当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。

不懂得volatile内容将会带来灾难。

0 0
原创粉丝点击