您的位置:首页 > 编程语言 > C语言/C++

找工作笔试面试经验总结(C语言基础部分)

2017-09-23 14:24 363 查看
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
以上的题目都是比较简单的,没什么难度,都是考的比较基础的知识点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: