2017年9月14号,辞去了在伟易达的工作,怎么说,待了两年了,提辞职不太好说出口,但人各有志,我还是希望能去外面接触更多的东西,也希望能够多认识一些人,丰富我的社交经验。
纵观好几个公司的笔试面试经验,都考得比较简单,笔试和面试不会是那种特别难的题目,基本上都是基础知识,所以我一再告诉我的师弟师妹,出来工作,除了一些比较牛逼的公司出的题比较异类以外,其余的绝大多数公司,考的题目都是比较基础的,所以,基础是非常重要的。下面我就根据我笔试的回忆,考的最多依然是C语言基础,写出以下考到的题目:
(1) ++a 和 a++的区别?哪个效率要高一些?
答:++”运算符被称为自增运算符。如果“++”运算符出现在变量的前面(++a(变量)),那么在表达式使用变量之前,变量的值将增加1。如果“++”运算符出现在变量之后((变量)a++),那么先对表达式求值,然后变量的值才增加1。
效率问题,可以参考这个博客:http://blog.csdn.net/gao1440156051/article/details/51570490
如以下程序:
#include <stdio.h> int main(void) { int a = 2 ; int b = 3 ; int c ; c = ++a - b++ ; printf("a=%d b=%d c=%d\n",a,b,c); return 0 ; }运行结果:
a=3,b=4,c=0
很明显,根据上面的理论可以得知,a是前加a,所以a是先加1后赋值,所以a = 2+1 = 3 ;
b是后加,所以b的值在c=++a - b++;这个表达式的时候,它的值不变,依然为3,但由于在后面使用printf进行打印的时候,由于b++的先赋值后加,所以b最终的结果为4。由于表达式c=++a - b++,b的值仅仅只是先赋值,所以b的值此时为3,a先加后赋值,所以a为3,可推出c=0。
(2)=和==的区别
#include <stdio.h> int main(void) { int a = 1 ; int b = 0 ; if(a=1) b = 3 ; if(a=2) b = 5 ; printf("b:%d\n",b); }运行结果为5。
为什么?因为=号是赋值操作,if(条件表达式)语句中,条件表达式只要为真,就会执行语句块里的程序,所以a=1为真,b=3,当a=2的时候,也为真,所以最终b=5。
#include <stdio.h> int main(void) { int a = 1 ; int b = 0 ; if(a==1) b = 3 ; if(a==2) b = 5 ; printf("b:%d\n",b); }运行结果为3。
为什么?因为==是关系运算符,此时相当于比较a和一个数是否相等,如果相等,则会执行语句块的内容,因此,a等于1,条件成立,所以最终结果b=3。
(3)值传递和地址传递
#include <stdio.h> int add(int x,int j) { x+= j*10 ; } int main(void) { int i ; int num = 100 ; for(i = 0 ; i < 5 ; i++) { add(num,i); printf("i=%d,num:%d\n",i,num); } return 0 ; }运行结果:
i = 0 , num = 100 ;
i = 1 , num = 100 ;
i = 2 , num = 100 ;
i = 3 , num = 100 ;
i = 4 , num = 100 ;
为什么?
调用add函数的时候,执行语句:num += i*10 ; 其实只是对该函数的形参进行操作,并没有对i和num进行操作,所以num的值没有进行任何更改,故打印的结果都是原始值100。
#include <stdio.h> int add(int *x,int j) { *x+= j*10 ; } int main(void) { int i ; int num = 100 ; for(i = 0 ; i < 5 ; i++) { add(&num,i); printf("i=%d,num:%d\n",i,num); } return 0 ; }输出结果:
i = 0 , num = 100 ;
i = 1 , num = 110 ;
i = 2 , num = 130 ;
i = 3 , num = 160 ;
i = 4 , num = 200 ;
为什么?此时,函数add的第一个参数传递的是num地址,这就是C语言间接引用的技巧,也就是地址传递了。这时候到了add函数里面,此时x的地址就是num的地址,x的操作等同于操作num,所以最后num的输出结果肯定是不同的。
(4)共用体大小端相关问题
#include <stdio.h> int main(void) { union{ int num ; unsigned char n[4] ; }q; int i ; q.num = 10 ; for(i = 0 ; i < 4 ;i++) printf("%x ",q.n[i]); return 0 ; }运行结果:
a 0 0 0
共用体,简单的理解也就是共用一段内存,也就是说此时共用体中的num和数组n的起始地址都是一样的,我们可以用:printf("num:%p\nn:%p\n",&q.num,&q.n);打出来看看。
当然,运行结果在大小端的影响下,可能不同。
大端存储:指的是数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端存储:指的是数据的低字节保存在内存的高地址中,而数据的高字节保存在内存的高地址中。在32位机中,
如果为小端模式,值为:a 0 0 0
如果为大端模式,值为:a0000000 0 0 0 0
以上的运行结果,可以说明,该32位机器的输出结果a 0 0 0是小端模式。
(5)用C语言实现冒泡排序:
参考以前的博客:http://blog.csdn.net/morixinguan/article/details/50647028
(6)用C语言实现单链表的删除和插入函数:
参考以前的博客:http://blog.csdn.net/morixinguan/article/details/77756216
(7)不调用库函数,实现strcpy函数的功能:
#include <stdio.h> #include <assert.h> char *strcpy(char *dest , const char *src) { //1.检查参数是否合法 assert(dest != NULL && src != NULL); //2.定义新的变量来接收,不要直接去操作原来的数据 char *_dest = dest ; const char *_src = src ; //3.进行赋值操作,判断是否到'\0' while((*_dest ++ = *_src++) != '\0'); //4.返回dest的地址 return _dest ; } int main(void) { char *p = "hello world!"; char buf[20] = {0}; strcpy(buf,p); printf("%s\n",buf); return 0 ; }(8)setjmp和longjmp
请分析一下程序的输出结果:
#include <setjmp.h> #include <stdio.h> static jmp_buf buf; main() { volatile int b; b =3; if(setjmp(buf)!=0) { printf("%d ", b); exit(0); } b=5; longjmp(buf , 1); }参考博客解答:http://blog.csdn.net/wangkeyen/article/details/50658998
(9)全局变量,局部变量各有什么特点?
全局变量储存在全局区,局部变量在栈区。全局变量作用于当前的位置到文件的结尾,局部变量仅仅只作用于当前栈所在的区域,一旦栈被释放,局部变量存储的数据即是无意义的。比如:一个函数结束后,该函数内所有的自动变量所占用的内存空间都被释放,释放的含义是:通知系统,这些内存已经是*的了,可以被其他代码改写了。没有被改写前,这些内存中还是原来的值,至于什么时候改写,那谁也不知道。所以返回它们的地址是没有任何意义的。
参考百度:https://zhidao.baidu.com/question/982178744566405419.html
(10)volatile的作用是什么?
修饰符告诉编译程序不要对该变量所参与的操作进行某些优化。
1.内存映射硬件
2.共享内存
(11)static的作用是什么?
在函数外部说明为static 的变量的作用域为从定义点到该文件尾部;在函数内部说明为static 的变量的作用域为从定义点到该局部程序块尾部。static还有其它的特性:
1.static 修饰的局部变量的数值是上一次函数调用结束之后的数值
2.static 还可以修饰全局变量或者函数。静态局部变量在定义的时候没有初始化,系统会给定 0 为默认的初始值
3.基于static关键字的作用,定义一个static变量,结合switch语句,很容易实现状态机。
(12)用C语言实现判断大小端的方法的程序
#include <stdio.h> #include <stdlib.h> //用指针的方式检测机器的大小端模式 int small_port() { int a = 1 ; char b = *((char *)(&a)) ; return b ; } int main(void) { int i = small_port(); if(1 == i) printf("小端模式\n"); else printf("大端模式\n"); return 0 ; }(13)变量数据范围的考查
在32位操作系统PC机上,运行以下程序:
#include <stdio.h> int main(void) { char a = 0x80 ; int b = a ; if(b < 0) b = 0; else b = 0x80; printf("b:%d \n",b); return 0 ; }运行结果:
b:0
为什么?char类型的变量的数据范围为-128 ~ +127,占用一个字节,char a = 0x80 , 0x80是正数128,显然已经越界,那么越界输出a则不是一个正数,而是一个负数。
关于C语言的数据范围的取值可以参考这个博客或者看C语言基础相关的书籍:
http://blog.csdn.net/abaloon/article/details/8173552
(14)三目运算符
#include <stdio.h> int main(void) { char a = 100 ; char c = a > 0 ? 'y' : 'n' ; printf("c:%c\n",c); return 0 ; }运行结果:
c: y
以上的题目都是比较简单的,没什么难度,都是考的比较基础的知识点。