第一次笔试题

http://blog.csdn.net/yicao821/article/details/6882582

这是我第一次面试笔试题,因为题目不多,并且都是些老生常谈的题目,于是我便在这记录了下来。一来可以分享下我的经历,二来也可以做为巩固。题目就六个,可以尝试自己回答,参考答案我已经给出(基本出自《牛叉公司面试题集之C和C++版本.pdf》)。

1、 static全局变量与普通的全局变量有什么区别?static 局部变量和普通局部变量有什么区别?static 函数与普通函数有什么区别?
答: 1) 全局变量(外部变量)的说明之前再冠以 static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域,  即只在定义该变量的源文件内有效,  在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。    
2) 从以上分析可以看出,  把局部变量改变为静态变量后是改变了它的存的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了作用范围。
3) static 函数与普通函数作用域不同,仅在本文件。只在当前源文件中明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包综上所述:
static全局变量与普通的全局变量有什么区别: 
static全局变量只初使化一次,防止在其他文件单元中被引用;    
static局部变量和普通局部变量有什么区别: 
static局部变量只被初始化一次,下一次依据上一次结果值;     
static函数与普通函数有什么区别: 
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝


2、c中内存分为那几个区分别有什么作用。内存分配有哪几种。
答:1)栈:用来存放函数的形参和函数内的局部变量。由编译器分配空间,在函数执行完后由编译器自动释放。2)堆:用来存放由动态分配函数(如malloc)分配的空间。是由程序员自己手动分配的,并且必须由程序员使用free释放。如果忘记用free释放,会导致所分配的空间一直占着不放,导致内存泄露。3)全局局:用来存放全局变量和静态变量。存在于程序的整个运行期间,是由编译器分配和释放的。4)文字常量区:例如char *c = “123456”;则”123456”为文字常量,存放于文字常量区。也由编译器控制分配和释放。程序代码区:用来存放程序的二进制代码。


内存分配方式有三种:
  [1]从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
  [2]在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  [3]从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

3、设有以下说明和定义:  
   typedef union  

   long i;  
   int k[5]; 
   char c; 
} DATE;   
  struct data 

   int cat; 
   DATE cow;  
double dog; 
} too;   
  DATE max;    
则语句 printf("%d",sizeof(struct data)+sizeof(max));的执行结果是:52
答:DATE 是一个 union, 变量公用空间. 里面最大的变量类型是 int[5], 占用 20 个字节. 所以它的大小是20.  data是一个struct, 每个变量分开占用空间. 依次为int4  +  DATE20  + double8 = 32. 所以结果是 20 + 32 = 52. 当然...在某些 16 位编辑器下, int 可能是 2字节,那么结果是 int2 + DATE10 + double8 = 20 

4、请写出一个函数实现字符串反转。例如:输入“abcd”倒序后变为“dcba”输出。
int main()    
{    
  char* src = "hello,world";    
  int len = strlen(src);     
  char* dest = (char*)malloc(len+1);//要为分配一个空间  
  char* d = dest;  
  char* s = &src[len-1];           //指向最后一个字符   
  while( len-- != 0 )    
   *d++=*s--;   

  *d = 0;            //尾部要加'\0'
  printf("%sn",dest);     
  free(dest);        // 使用完,应当释放空间,以免造成内存汇泄露  
  dest = NULL;       //防止产生野指针  
  return 0;   
 } 

5、请写一个函数用于判断断处理器大小端。
void checkCPU()

 union w
 {
  int a;
  char b;
 }c;
 c.a = 1;

  if (c.b == 1 ) {
  printf("Little_endian\n");
 }
 else
  printf("Big_endian\n");

}
linux内核中在arch/arm/kernel/setup.c中有这样的定义:
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
可以仿着写,这样你印象更好。

6、写个函数实现冒泡排序。
 //时间复杂度为0(n*n); 
void BubbleSort(elemtype x[],int n) 

 Int i,j; 
 BOOL exchange;  //记录交换标志 
for(i=1;i<n;++i)    //最多做n-1趟排序 
 { 
Exchange = false; 
For(j=n-1;j>=i;--j) 

 If(x[j]>x[j+1]) 
 { 
    x[0] = x[j]; 
    X[j] = x[j+1]; 
    X[j+1] = x[0]; 
    Exchange = true;   //发生了交换,设置标志为真. 
 } 

if (!Exchange )      //为发生替换,提前终止算法 
return; 
  
 } 
}

人生简短,价值无限,告诉人家你是独一无二的,你就是你,你成就你。

1、

不要递给我花里胡俏的简历,给我一点简洁(不是简单)而能突出你自己的表达——面对成千上万的求职者,你真的以为HR会去看你那封100个人有99个差不多的求职信、和装订得像书本一样的简历模板内容吗?­

2、

不要对我说太多的自我介绍,我不敢说3、5分钟我就准确判断了你,但是30秒之内我就定格了你的第一印象;我之所以很快结束你的面试,是因为你的后面排队的人真是太多,我也曾经作为毕业生这样苦苦的等待,我只是为了给更多的人一个和你一样平等的机会,而后我会挑选请你到我办公室复试;你认为我给你的时间太少,而流露出失望(自己是不是没被看中了?)眼神的那一刹那,你就丢失了再次获得复试的机会。我永远坚持:你的信心就是我的希望。你的岗位机会不是我给你的,而是你自己争取的。

3、

不要一副“只要你招我我什么都肯做”的姿态,这样给我一种“卖身”的感觉,我请你是因为你会为公司创造价值,所以不是你“求”职,而是我“请”你。这不是叫你抬到姿态,而只是希望你抬起胸膛。

4、

不要不敢说出和写下你毕业的学校,无论她是如何的差,你是从那里走出来的,因为我绝对不会要这样的人:看到他父母的时候,因为他们的背景不好而不敢认他们;或者有一天离开我的公司,去到一个更大的公司面试的时候,不好意思说我是来自一个不是500强的公司。对公司来说,你的价值和价值观,决定了一切。英雄莫问出处,如果你是一个狗熊,哪怕你从天堂走出来,也还是狗熊。

5、

不要给我罗列一大堆你的学习成绩和从事的所谓实习(因为很多毕业生也曾经到我这里来兜一圈,参观一下,盖个章名曰“实习”),你只需要挑选一件特别的事情,要点式地说明过程和结果,让我知道你是怎样做事的。

6、

不要不敢用眼睛看着我,你不敢瞧我的时候我也瞧不起你。

7、

不要在回答“你的薪酬要求”的时候,多了那么多废话。其实我不在乎你说的是5000,还是1500,我在乎的是你说出一个数字的那种语气、眼神。我尊重每个人都有自估劳动力价值的权利。我喜欢干脆利落的同事,干脆利落是一种自信,是一种做事风格,也是一种做人态度。我会固执的认为:你说出这个数字前后带了多少个字符,就表示你做事有多拖泥带水;或者你的自我认识和自信是多么摇摆不定。­

8、

应试者是以好的直觉做出明智的选择,还是只是瞎蒙呢?当应试者在某个问题上卡住时是找借口呢,还是表现出对问题的真正的好奇心,把这看成学习的机会呢?我发现这些信息与他们的测试成绩一样有用。

今天老大让我针对一个面试者出些嵌入式方面的面试题,主要是想对他的技术深度进一步了解。我就出了下面这些问题,每个问题背后都是考察一个嵌入式程序员应该具备的相关技能。当然这些只是我的个人理解,不一定正确。在此与大家分享,只是希朋友们能够得到一点点启发:如何抓住每一个契机展现你的与众不同?同样的技术问题,很多人可能都能够回答得对,但有些人只是知其然而不知所以然。其实面试官每一个问题背后通常都隐藏着一个考察点。如果我们能够透过问题看到背后的实质,在回答出答案的时候还能够借机发挥,我相信90和100分的差别就出来了。哪个面试官不喜欢招一个喜欢思考、能透过现象看本质的员工呢~

下面我们来看看嵌入式C面试题背后到底藏何玄机~。以下仅是个人的一些想法,欢迎大家讨论,拍砖的轻点~~

 

1、  int a=2,b=11,c=a+b++/a++; 则c值为多少?

【考点】编码规范。

表面上考察你对运算符优先级的掌握程度,但实际上优先级这些玩意很难死记硬背得住?大家的疑惑不就是运算符的结合顺序么?那么如何去避免呢?c=a+((b++)/(a++))不就行了么,其实问题背后考察的是你的编码规范,如何写清晰易懂的代码,如何在一个团队中让自己的代码狠容易毫无偏差的让新人看懂~

 

2、  Static用在全局变量定义和函数内部局部变量定义有何区别?

【考点】编码规范及模块化设计。

Static变量的两个属性涉及存储位置及可见域。在大型的程序设计中static全局变量可以有效的避免名字空间的重复及无意的变量引用,这样可以有效的提高程序设计的安全性,同时也利用模块化作业

 

3、  在程序设计中哪些地方需要使用define?如何用define来定义一年内有多少小时的常量?

【考点】可移植性。

嵌入式程序设计的特点就是软硬件平台可变性,有效利用define常量可以提高程序的可移植性,这样改动方便,不易出错

 

4、  Define宏语句和inline函数有什么区别?

【考点】时空效率及宏的副作用。

嵌入式系统平台通常存储资源有限,但同时又对实时性有一定的要求,二者如何权衡需要考虑。Define宏语句相对于函数调用能提高运行时间性能,但消耗了空间,并且不标准的宏语句定义在不标准的编码中更容易出现副作用,因此inline函数则是define语句的完美替代品。小资金干大事正是嵌入式的终极目标!

 

5、  哪些地方可以用到constconst变量和函数输入参数用const修饰有哪些作用?

【考点】程序设计可靠性。

Const只读变量可以有效克服define常量的一些弊端,如无类型安全检查。Const形参可以有效避免程序内部更改无意的更改。人非圣贤孰能无误,所以我们要将这些可能的失误统统交给智能的编译器,这样就可以将错误扼杀在摇篮中

 

6、  Intshortchar32位平台下各占几个字节?一个结构体含有intshortchar变量各一个,结构体占据的总内存空间多少?

【考点】跨平台移植。

嵌入式并非x86,其硬件平台具备很大的差异性,同为int在不同的架构体系下可能占据的字节数是不一样的。不同的平台也有不同的编译器,其在变量对齐方面可能有不同的特性。因此在结构体定义时如何设计成员变量的顺序以有效减少占据的内存空间,以及如何填充特定字段保证访问对齐问题,都是嵌入式系统结构体设计时应该考虑的跨平台可移植性问题

 

7、  如何将unsigned int明确定义为一个32位类型?definetypedef有何区别?

【考点】跨平台移植。

define和typedef都可以实现变量类型重定义,但是typedef类型的指针变量可以有效去除变量定义的二义性。在嵌入式的工程项目中,通常为了保证数据类型的统一且便于跨平台移植时修改数据类型方便,通常都会单独定义一个数据类型的头文件,把所有用到的数据类型typedef成所熟悉的形式

 

8、  有没有用过volatile?有哪些典型的适用场合?

【考点】编译优化的副作用。

通常为了提高程序运行的效率,编译器会自动进行一些优化,如将变量放在寄存器中,以减少存储器访问次数,在数据长期未变时不重新读取内存等等。但是优化有时会带来问题,如硬件寄存器、多任务共享变量、中断和主程序共享变量,优化有可能带来数据访问不一致性的问题,因此对于这些个别变量,我们需要用volatile声明告诉编译器取消优化

 

9、  参数传递有哪些形式?寄存器和堆栈传递各有什么优缺点?

【考点】编译优化、调用性能、接口设计。

每种体系结构及对应的编译器对参数传递都有自己的规定。参数传递并非总是通过堆栈进行的,参数入栈出栈是需要耗费时间的,编译器总是尽量优化利用寄存器来传递参数,因为寄存器的访问效率要高,但当参数过多时,将放弃优化从而用栈传递参数。因此为了提高调用性能,应尽量减少参数个数,太多时可以将所有参数重新定义为一个结构体,利用结构体指针来传递参数。在函数接口设计时应考虑硬件平台和编译器的特性,以灵活定义参数形式

 

10、 中断服务程序设计应注意的问题?中断触发方式的选择?中断处理太长怎么办?中断处理程序如何与主应用程序交互?

【考点】中断服务程序设计。

嵌入式程序最大的特点是经常需要和硬件打交道,中断是接收外界输入的典型方式,通常都决定了系统运行流程,因此如何高效不丢失的处理中断是每个嵌入式程序员应考虑的问题

 

11、 TCP/IPOSI七层模型是如何划分的?各层的功能,这么设计有什么好处?

【考点】层次化软件设计保证可移植性。

分层模型最大的好处就是某一层变化了,只要其提供上层的接口未变,那么上层就无需做任何改动。因此只需要更改本层的实现即可。嵌入式平台因为软硬件多变性,为了最大限度的利用先前的成果,软件设计一定要遵循这种层次化模型,这样才能保证其可移植性

 

12、 TCPUDP的区别?各种网络互连设备都用在哪一层?如何建立链接?如何进行拥塞控制?

【考点】协议设计可靠性及缓冲区设计管理。

TCP和UDP的最大区别在于可靠性,TCP通过三次握手协议及超时机制安全可靠的建立或者释放连接。协议设计最大的问题就是如何保证效率合可靠性,TCP的设计为我们提供了一个参考。而滑动窗口机制可以有效的进行拥塞控制,但窗口大小的设计则关系到内存利用率及缓冲效率可靠性等问题。在嵌入式的驱动程序设计中,经常会开辟缓冲区来进行流量控制及防止数据覆盖,缓冲区的大小设计则需要更加具体的应用情况设计才能保证可靠性合灵活性

本文来自:http://blog.csdn.net/sailor_8318/archive/2008/11/10/3270149.aspx
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值